我在这里和这里发现可以使用Cython将Python转换为C,但我找不到任何一步一步的例子.假设我有一个简单的功能:
foo.pyx
cdef void foo(double* x): x[0] = 0.0
setup.py
from distutils.core import setup from Cython.Build import cythonize setup( ext_modules = cythonize("foo.pyx") )
然后我运行:python setup.py build_ext --inplace来获取foo.c和foo.so文件(以及构建目录).好吧,我想在main.c中使用翻译(我希望)的foo函数.我应该把什么放入main.c文件以及如何编译它以便能够使用foo函数?我正在使用gcc.
远非ac专家,但对于我使用ubuntu,以下工作:
main.c中:
#include "foo_api.h" #includeint main(int argc, char *argv[]) { Py_Initialize(); initfoo(); import_foo(); double arr[5] = {1,2,3,4,5}; int i = 0; foo(arr); for(i = 0; i < 5; i++) { printf("%f\n", arr[i]); } Py_Finalize(); return 0; }
foo.pyx:
cdef public api foo(double* x): x[0] = 0.0
从同一目录:
$ cython foo.pyx
然后:
$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -o foo *.c -lpython2.7
然后跑吧.
$ ./foo 0.000000 2.000000 3.000000 4.000000 5.000000
我pkg-config --cflags python
以前得到了旗帜:
$ pkg-config --cflags python -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7
不调用Py_Initialize(初始化Python解释器.在嵌入Python的应用程序中,应该在使用任何其他Python/C API函数之前调用它;),您将获得:
Fatal Python error: PyThreadState_Get: no current thread Aborted (core dumped)
没有initfoo()
或 import_foo()
你得到一个:
Segmentation fault (core dumped)
如果你不调用Py_Finalize:
Py_Initialize
第二次调用时没有操作(没有先调用Py_Finalize()).
要从运行的文档中获取delorean示例:
main.py:
#include "delorean_api.h" #includeVehicle car; int main(int argc, char *argv[]) { Py_Initialize(); initdelorean(); import_delorean(); car.speed = atoi(argv[1]); car.power = atof(argv[2]); activate(&car); Py_Finalize(); return 0; }
delorean.pyx:
ctypedef public struct Vehicle: int speed float power cdef api void activate(Vehicle *v): if v.speed >= 88 and v.power >= 1.21: print "Time travel achieved" else: print("Sorry Marty")
程序是一样的,唯一的变化是我必须使用ctypedef
Vehicle结构,否则在main或者我在main中使用的使用struct Vehicle car;
:
$ cython delorean.pyx $ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -o delorean *.c -lpython2.7 $ ./delorean 1 1 Sorry Marty $ ./delorean 100 2 Time travel achieved
您也可以在不使用Py_Initialize
等的情况下使用它......
在foo.pyx
你只需要公开功能:
cdef public foo(double* x): x[0] = 0.0
我添加#include
刚刚foo.h
在main.c中导入并删除Py_Initialize();
等.只是导入python.h
对我不起作用,但对于每个人来说可能并非如此.
#include#include "foo.h" #include int main(int argc, char *argv[]) { double arr[5] = {1,2,3,4,5}; int i = 0; foo(arr); for(i = 0; i < 5; i++) { printf("%f\n", arr[i]); } return 0; }
编译是一样的:
$ cython foo.pyx $ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -o foo *.c -lpython2.7 $ ./foo 0.000000 2.000000 3.000000 4.000000 5.000000
如果您正在使用api版本,那么只需按照文档包含api标头或反之亦然但请注意,您应该在给定的C文件中包含modulename.h或modulename_api.h,而不是两者都包含,否则您可能会遇到双重冲突定义.
为了对delorean示例执行相同的操作,我必须使用它libc.stdio
来打印字符串以避免分段错误:
from libc.stdio cimport printf ctypedef public struct Vehicle: int speed float power cdef public void activate(Vehicle *v): if v.speed >= 88 and v.power >= 1.21: printf("Time travel achieved\n") else: printf("Sorry Marty\n")
主要:
#include#include #include "delorean.h" Vehicle car; int main(int argc, char *argv[]) { car.speed = atoi(argv[1]); car.power = atof(argv[2]); activate(&car); return 0; }
返回值可能更有意义:
ctypedef public struct Vehicle: int speed float power cdef public char* activate(Vehicle *v): if v.speed >= 88 and v.power >= 1.21: return "Time travel achieved" return "Sorry Marty"
主要:
#include#include #include "delorean.h" Vehicle car; int main(int argc, char *argv[]) { car.speed = atoi(argv[1]); car.power = atof(argv[2]); printf("%s\n",activate(&car)); return 0; }