[英]Minimal example of wrapping C code with Cython- passing int and struct
The code that I show below works, but I am not exactly sure why . 我在下面展示的代码有效, 但我不确定为什么 。
I am using: 我在用:
This code is taken primarily from this video tutorial and git page , but unfortunately did not work for me 'out of the box'. 这段代码主要来自这个视频教程和git页面 ,但遗憾的是我没有“开箱即用”。
The goal of this wrapping to provide access through Python to a trivial C function, which accepts either integers or a structure of integers and adds them together. 这种包装的目的是通过Python提供对一个简单的C函数的访问,该函数接受整数或整数结构并将它们加在一起。
There are 5 files needed for this, described below: 这需要5个文件,如下所述:
adder.c
: C code of the two adder functions: add (scalar inputs) and pair_add (struct inputs) adder.c
:两个加法器函数的C代码: add (标量输入)和pair_add (struct输入) adder.h
: header file for adder.c adder.h
: adder.h
头文件 c_adder.pxd
: a cython header file- essentially tells cython which parts of the main header file to pay attention to c_adder.pxd
:一个cython头文件 - 本质上告诉cython主头文件的哪些部分需要注意 cy_adder.pyx
: the cython code used to define both functions in the python namespace cy_adder.pyx
:用于在python命名空间中定义两个函数的cython代码 setup.py
: a distutils file which performs the compiling of the cython code setup.py
:一个distutils文件,用于执行cython代码的编译 and the process produces two files 并且该过程生成两个文件
c_adder.c
: an intermediate cython c file c_adder.c
:一个中级cython c文件 c_adder.so
: the python module which can be imported into a namespace c_adder.so
:可以导入命名空间的python模块 The input files are below: 输入文件如下:
adder.c adder.c
#include <stdlib.h>
#include "adder.h"
int
pair_add(PAIR * ppair) {
return ppair->x + ppair->y;
}
int
add(int x, int y) {
return x + y;
}
adder.h adder.h
typedef struct {
int x;
int y;
} PAIR;
int pair_add(PAIR * ppair);
int add(int, int);
c_adder.pxd c_adder.pxd
cdef extern from "adder.h":
ctypedef struct PAIR:
int x
int y
int add(int x, int y)
int pair_add(PAIR * ppair)
cy_adder.pyx cy_adder.pyx
cimport c_adder
def add(x, y):
return c_adder.add(x, y)
def pair_add(x, y):
cdef c_adder.PAIR pair
pair.x = x
pair.y = y
return c_adder.pair_add(&pair)
setup.py setup.py
from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
ext_modules = cythonize([Extension("cy_adder", ["cy_adder.pyx",'adder.c'])])
setup(
name = 'Hello world app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
I was able to successfully create a .so file by running 我能够通过运行成功创建.so文件
$ python setup.py build_ext --inplace
In the same directory as the above files. 在与上述文件相同的目录中。 It is then possible to load
cy_adder
into the namespace of a python interpreter. 然后可以将
cy_adder
加载到python解释器的命名空间中。
In the setup declaration, I have included adder.c
as an auxiliary module. 在设置声明中,我将
adder.c
作为辅助模块包含在内。
If I don't do this I get the following error when I import the .so
file: 如果我不这样做 ,我导入
.so
文件时会出现以下错误:
ImportError: dlopen(./cy_adder.so, 2): Symbol not found: _add
Referenced from: ./cy_adder.so
Expected in: flat namespace
in ./cy_adder.so
Is there a step that I am missing which would mean that I don't need to explicitly pass adder.c
along with my setup command? 是否有一个我遗漏的步骤意味着我不需要显式传递
adder.c
和我的setup命令? Am I opening myself up to some potential instability by doing this? 通过这样做,我是否打开了自己的潜在不稳定性?
The adder.c
file needs to be referenced somewhere so it knows where to find the implementation of add
. 需要在某处引用
adder.c
文件,以便知道在哪里可以找到add
的实现。 As you discovered, listing adder.c
as an additional source file works. 如您
adder.c
,将adder.c
列为附加源文件。 A more common way to use external (shared) C libraries is to compile it as libadder.so and link it via the libraries
parameter in your Extension declaration. 使用外部(共享)C库的一种更常见的方法是将其编译为libadder.so,并通过Extension声明中的
libraries
参数链接它。
For something this simple you could also just write 对于这个简单的东西你也可以写
cdef extern from "adder.c": # note the .c
int add(int x, int y)
...
or put the entire implementation in the .h file. 或者将整个实现放在.h文件中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.