所以我想通过cython从c调用一些python代码。我设法从c调用cython代码。而且我还可以从cython调用python代码。但是,当我将它们全部加在一起时,会丢失一些东西。
这是我的python代码(quacker.pyx
):
def quack():
print "Quack!"
这是我的cython“bridge”(
caller.pyx
):from quacker import quack
cdef public void call_quack():
quack()
这是C代码(
main.c
):#include <Python.h>
#include "caller.h"
int main() {
Py_Initialize();
initcaller();
call_quack();
Py_Finalize();
return 0;
}
运行此命令时,出现以下异常:
Exception NameError: "name 'quack' is not defined" in 'caller.call_quack' ignored
我怀疑缺少的部分:
initquacker()
quacker.h
quacker.h
-only quacker.c
caller.c
不会导入quacker.h
或调用initquacker()
我不太确定是否有可能做我想做的事情,但在我看来应该如此。我很想听听您可能有任何意见。
编辑:
这就是我进行cythonize/编译/链接/运行的方式:
$ cython *.pyx
$ cc -c *.c -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
$ cc -L/System/Library/Frameworks/Python.framework/Versions/2.7/lib -L/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config -lpython2.7 -ldl *.o -o main
$ ./main
最佳答案
如果将quacker.pyx
重命名为quacker.py
,则实际上一切正确。唯一的问题是您的程序将不会在当前目录中搜索python模块,从而导致输出:
Exception NameError: "name 'quack' is not defined" in 'caller.call_quack' ignored
但是,如果将当前目录添加到PYTHONPATH环境变量,则输出将成为您期望的输出:
$ PYTHONPATH=".:$PYTHONPATH" ./main
Quack!
运行python shell时,根据documentation,当前目录(或包含脚本的目录)会自动添加到
sys.path
变量中,但是当使用Py_Initialize
和Py_Finalize
创建简单程序时,似乎不会发生。由于PYTHONPATH变量也用于填充sys.path
python变量,因此上述解决方法会产生正确的结果。或者,您可以在
Py_Intialize
行下方,仅通过执行一些指定为字符串的python代码,向sys.path
添加一个空字符串,如下所示:PyRun_SimpleString("import sys\nsys.path.insert(0,'')");
重新编译后,只需运行
./main
就可以了。编辑
实际上,如果您按照问题中的说明运行代码,将会看到发生了什么,这很有趣,因此无需重命名
quacker.pyx
文件。在这种情况下,initcaller()
函数尝试导入quacker
模块,但是由于不存在quacker.py
或quacker.pyc
,因此无法找到该模块,并且initcaller()
函数产生错误。现在,通过引发异常以Python方式报告此错误。但是
main.c
文件中的代码不会对此进行检查。我不是专家,但是在我的测试中,在initcaller()
下面添加以下代码似乎可行:if (PyErr_Occurred())
{
PyErr_Print();
return -1;
}
程序的输出将变为以下内容:
Traceback (most recent call last):
File "caller.pyx", line 1, in init caller (caller.c:836)
from quacker import quack
ImportError: No module named quacker
通过在
initquacker()
之前调用initcaller()
函数,模块名称quacker
已经被注册,因此在initcaller()
内部完成的导入调用将检测到它已经被加载,并且该调用将成功。关于python - 通过cython从c调用python代码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22589868/