gpt4 book ai didi

python - Cython 作为 Python 到 C 转换器的示例程序

转载 作者:太空狗 更新时间:2023-10-29 17:45:46 26 4
gpt4 key购买 nike

我找到了 herehere可以使用 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 的我来说,以下工作:

主.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 第二次调用时出现空操作(没有先调用 Py_Finalize())。

获取delorean要运行的文档中的示例:

主要.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 或 use 中我没有使用 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 <python2.7/Python.h>刚刚进口foo.h在 main.c 中并删除了 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 ,反之亦然但是,请注意,您应该在给定的 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 <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"

主要内容:

#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;
}

关于python - Cython 作为 Python 到 C 转换器的示例程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34480973/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com