从C++调用Cython函数

20 投票
3 回答
12144 浏览
提问于 2025-04-16 16:00

我有一个C++的库,它有一个Python的包装器(是用SWIG写的)。这个库可以执行一些小的用户自定义代码(叫做回调),比如对向量进行逐元素的操作。也就是说,除了简单的加法,你可以做任何你想要的二元函数。目前的做法是接受一个可调用的Python对象作为这个二元函数,然后调用它。这样是可以的,但每次迭代都要在Python和C++之间来回跳,速度大约慢了80倍。

我该如何编写/构建/导入一个Cython函数,让它可以直接被我的C++库调用呢?

编辑:如果我只用C的话,我会写类似这样的代码:

EWise(double (*callback)(double, double))

然后EWise会像这样调用 callback(10, 20);。我希望 callback 是用Cython写的,用户可以自定义名字,并且需要通过某种方式将它的指针传递给我的C++库。这个“某种方式”我还不太清楚。

3 个回答

0

你可以看看这篇文章,内容是关于如何把Python嵌入到其他应用程序中的,这可能会对你有帮助。

2

你可以通过使用纯粹的 cdef 函数来实现这个目标:

# declare the prototype of your function
ctypedef void (*callback_ptr)(int arg)

# declare your function as cdef
cdef void my_callback(int arg):
    print 'doing some python here', arg

# now, you can use the cdef func as a callback
# in pure C !
cdef void run():
    cdef callback_ptr p = my_callback
    p(42)

if __name__ == '__main__':
    run()

注意:你可以使用 "cython -a" 命令来查看运行的内容中没有涉及任何 Python 代码。因此,它可以和你的 C 库一起工作。

18

使用cython的一个窍门就是要用到一个关键词叫做 public

cdef public double cython_function( double value, double value2 ):
    return value + value2

接着,你可以用命令 cythonize <your_file.pyx>,这个命令会生成一个 <your_file.c> 文件,同时还会创建一个头文件 <your_file.h>,你可以把这个头文件包含进来。或者,你也可以自己手动创建这个头文件:

#ifdef __cplusplus {
extern "C"
#endif

double cython_function( double value, double value2 );

#ifdef __cplusplus
}
#endif

更新

然后,借助Python的一些功能,你可以使用 ctypes的回调机制

func_type = CFUNCTYPE(c_double, c_double, c_double)

your_library.set_callback_function ( func_type(user_modules.cython_function) )

撰写回答