Cython 作为 Python 到 C 转换器的示例程序
Example program of Cython as Python to C Converter
我发现 here and here 可以使用 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。
远非 c 专家,但对我来说使用 ubuntu,以下工作:
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 解释器。在嵌入 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
a no-op 第二次调用时(没有先调用 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:
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
中你只需要使函数public:
cdef public foo(double* x):
x[0] = 0.0
我添加了 #include <python2.7/Python.h>
刚刚在 main.c 中导入了 foo.h
并删除了 Py_Initialize();
等。仅导入 python.h
对我来说不起作用,但这可能不会每个人都是这样。
#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 header,反之亦然 但是,请注意,您应该包含modulename.h 或 modulename_api.h 在给定的 C 文件中,而不是两者,否则你可能会得到冲突的双重定义。
为了对 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 <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;
}
return 值可能更有意义:
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 <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;
}
我发现 here and here 可以使用 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。
远非 c 专家,但对我来说使用 ubuntu,以下工作:
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 解释器。在嵌入 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
a no-op 第二次调用时(没有先调用 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:
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
中你只需要使函数public:
cdef public foo(double* x):
x[0] = 0.0
我添加了 #include <python2.7/Python.h>
刚刚在 main.c 中导入了 foo.h
并删除了 Py_Initialize();
等。仅导入 python.h
对我来说不起作用,但这可能不会每个人都是这样。
#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 header,反之亦然 但是,请注意,您应该包含modulename.h 或 modulename_api.h 在给定的 C 文件中,而不是两者,否则你可能会得到冲突的双重定义。
为了对 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 <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;
}
return 值可能更有意义:
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 <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;
}