Cython作为Python到C转换器的示例程序 [英] Example program of Cython as Python to C Converter
问题描述
我在此处和此处可以使用Cython将Python转换为C,但是我找不到任何分步示例。假设我有一个简单的函数:
I found here and here that one can use Cython to convert Python to C, but I cannot find any step-by-step example. Let's say I have a simple function:
foo.pyx
cdef void foo(double* x):
x[0] = 0.0
来自distutils.core的b
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函数。为了能够使用foo函数,我应该在main.c文件中放入什么内容以及如何对其进行编译?我正在使用gcc。
then I run: python setup.py build_ext --inplace to get foo.c and foo.so files (and build directory). Well, I would like to use translated (I hope) foo function in main.c. What should I put into main.c file and how to compile it in order to be able to use foo function? I am using gcc.
推荐答案
从ac专家那里回来,但是对我来说,使用ubuntu时,以下作品:
Far from a c expert but for me using ubuntu, the following works:
main.c:
#include "foo_api.h"
#include <stdio.h>
int 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解释器。在应用程序embeddi中ng Python,应在使用任何其他Python / C API函数之前调用它; ),您将获得:
Without calling Py_Initialize (Initialize the Python interpreter. In an application embedding Python, this should be called before using any other Python/C API functions;), you will get:
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"
#include <stdio.h>
Vehicle 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:
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结构一起使用,或者在主体中使用或使用我没有使用 struct车辆;
在主体中使用:
The procedure is the same, the only change was I had to use ctypedef
with the Vehicle struct or else in main or use I had t use struct Vehicle car;
in main:
$ 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
等...
You can also get it to work without using Py_Initialize
etc...
在 foo.pyx
中,您只需要使函数public:
In foo.pyx
you just need to make the function public:
cdef public foo(double* x):
x[0] = 0.0
我添加了 #include< python2.7 / Python.h>
刚刚在main.c中导入了 foo.h
并删除了 Py_Initialize();
等。仅导入了 python.h
不适用于我,但并非所有人都可以。
I added #include <python2.7/Python.h>
just imported foo.h
in main.c and removed Py_Initialize();
etc. Just importing python.h
would not work for me but that may not be the case for everyone.
#include <python2.7/Python.h>
#include "foo.h"
#include <stdio.h>
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,而不要同时包含二者,否则可能会导致冲突的双重定义。
If you are using the api version then just include the api header or vice versa as per the docs However, note that you should include either modulename.h or modulename_api.h in a given C file, not both, otherwise you may get conflicting dual definitions.
要执行相同的操作在delorean示例中,我不得不使用 libc.stdio
打印字符串以避免分段错误:
To do the same with the delorean example I had to use libc.stdio
to print the strings to avoid a segmentation fault:
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")
main:
#include <python2.7/Python.h>
#include <stdio.h>
#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"
main:
#include <python2.7/Python.h>
#include <stdio.h>
#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;
}
这篇关于Cython作为Python到C转换器的示例程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!