我在下面显示的代码有效,但我不确定为什么。
我正在使用:
此代码主要来自this video tutorial和git page,但遗憾的是,“开箱即用”并不适用于我。
这种包装的目的是通过Python提供对一个简单的C函数的访问,该函数接受整数或整数结构并将它们加在一起。
这需要5个文件,如下所述:
adder.c
:两个加法器函数的C代码: add (标量输入)和 pair_add (结构输入)adder.h
:adder.c的头文件c_adder.pxd
:一个cython头文件 - 基本上告诉cython要关注主头文件的哪些部分cy_adder.pyx
:用于在python命名空间中定义两个函数的cython代码setup.py
:执行cython代码编译的distutils文件并且该过程生成两个文件
c_adder.c
:一个中级cython c文件c_adder.so
:可以导入命名空间的python模块输入文件如下:
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
typedef struct {
int x;
int y;
} PAIR;
int pair_add(PAIR * ppair);
int add(int, int);
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
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
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
)
我能够通过运行
成功创建.so文件$ python setup.py build_ext --inplace
与上述文件位于同一目录中。然后可以将cy_adder
加载到python解释器的命名空间中。
在设置声明中,我已将adder.c
作为辅助模块。
如果我不这样做我导入.so
文件时出现以下错误:
ImportError: dlopen(./cy_adder.so, 2): Symbol not found: _add
Referenced from: ./cy_adder.so
Expected in: flat namespace
in ./cy_adder.so
是否有一个我遗漏的步骤,这意味着我不需要显式传递adder.c
和我的设置命令?通过这样做,我是否打开了自己的潜在不稳定性?
答案 0 :(得分:2)
需要在某处引用adder.c
文件,以便知道在哪里找到add
的实现。如您所见,列出adder.c
作为附加源文件可以正常工作。使用外部(共享)C库的一种更常见的方法是将其编译为libadder.so,并通过Extension声明中的libraries
参数将其链接。
对于这么简单的事情你也可以写
cdef extern from "adder.c": # note the .c
int add(int x, int y)
...
或将整个实现放在.h文件中。