我正在尝试创建一个Cython包装器,因此我可以从C调用Python代码。我遇到导入问题,因为我希望包装器与原始代码分开。
调用导入的函数时,下面的代码以 segfault 结尾。如果代码被编写为python模块并通过import
导入,则程序会显示name ... is not defined
。当一切都在一个文件中并且没有涉及导入时(实际上由Cython生成的代码在cimporting时失败),问题不会出现。当libcimpy.pyx从其他python脚本导入(编译为.so或live)时,代码也能正常工作
我准备了一个最小的例子。这远非实际代码,但涵盖了原则。
cimpPy.pyx:示例python代码(转换为Cython)
cdef sum(a, b):
return a + b
cimpPy.pxd
cdef sum(a, b)
libcimpy.pyx(胶水Cython代码)
cimport cimpPy
cdef public int cSum(int a, int b):
return cimpPy.sum(a, b)
ci.c(c代码,我们想从中调用cimpPy)
#include <stdio.h>
#include <stdlib.h>
#include <Python.h>
#include "libcimp.h"
int main(int argc, char **argv) {
Py_Initialize();
initlibcimp();
int a = 2;
int b = 3;
int c = cSum(a, b);
printf("sum of %d and %d is %d\n", a, b, c);
Py_Finalize();
return 0;
}
生成文件
EXECUTABLE = ci
OBJS = ci.o
CC = gcc
CFLAGS = -g -I/usr/include/python2.7 -I$(shell pwd)
LINKER = g++
LDFLAGS = -L$(shell pwd) $(shell python-config --ldflags) -lcimp
.PHONY: clean cython
all: cython $(EXECUTABLE)
cython:
python setup.py build_ext --inplace
.c.o:
$(CC) $(CFLAGS) -c $<
$(EXECUTABLE) : $(OBJS)
$(LINKER) -o $(EXECUTABLE) $(OBJS) $(LDFLAGS)
clean:
rm -rf *.o *.so libcimp.c libcimp.h core build $(EXECUTABLE)
setup.py
from distutils.core import setup, Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext
extensions = [
Extension("libcimp", ["libcimp.pyx"])
]
setup(
name = "CIMP",
cmdclass = {"build_ext": build_ext},
ext_modules = cythonize(extensions)
)
我打算实现的是能够将Python代码插入更大的C系统。假设用户将能够自己编写Python。 C代码是一个模拟引擎,可以在环境中的代理上运行。这个想法是代理和环境的行为可以在python中指定,并在必要时传递给引擎进行评估。最好的比喻是map reduce系统,其中Python脚本是映射器。在这个意义上,我想从C调用Python,而不是相反。
将所有内容转换为Cython,同时引人注目的是大型活动。
这是正确的做法吗?为什么导入只能在python解释器下工作而不能在外部嵌入时工作?任何建议和参考文章或文件表示赞赏。
答案 0 :(得分:2)
在此代码中,initlibcimp()
实际上已失败,但您无法立即看到它,因为错误是通过设置python异常来报告的。我不是100%确定这是正确的方法,但我可以通过在调用下面添加以下代码来查看错误:
if (PyErr_Occurred())
{
PyErr_Print();
exit(-1);
}
然后,程序将输出:
Traceback (most recent call last):
File "libcimpy.pyx", line 1, in init libcimpy (libcimpy.c:814)
cimport cimpPy
ImportError: No module named cimpPy
cimpPy
模块尚未定义的原因是,您需要在致电initcimpPy()
之前致电initlibcimp
。