所以我想通过cython从c调用一些python代码。我设法从c调用了cython代码,也可以从cython调用了python代码。但当我把它们加在一起时,有些东西就不见了。
这是我的python代码(quacker.pyx
):
def quack():
print "Quack!"
这是我的cython“桥”(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/compile/link/run:
$ 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中我添加了
强制Cython生成
.h
文件。总的来说:
如果将
quacker.pyx
重命名为quacker.py
,实际上一切都是正确的。唯一的问题是您的程序不会在当前目录中搜索python模块,从而导致输出:但是,如果将当前目录添加到PYTHONPATH环境变量中,则输出将成为您期望的目录:
运行python shell时,根据documentation,当前目录(或包含脚本的目录)会自动添加到
sys.path
变量中,但是在使用Py_Initialize
和Py_Finalize
创建简单程序时,似乎不会发生这种情况。由于PYTHONPATH变量还用于填充sys.path
python变量,因此上面的解决方法会产生正确的结果。或者,在
Py_Intialize
行下面,只需执行一些指定为字符串的python代码,就可以向sys.path
添加空字符串,如下所示:重新编译之后,只需运行
./main
就可以了。编辑
如果您按照问题中指定的方式运行代码,那么在不重命名
quacker.pyx
文件的情况下,查看发生了什么事情实际上是很有趣的。在这种情况下,initcaller()
函数尝试导入quacker
模块,但由于不存在quacker.py
或quacker.pyc
,因此找不到该模块,并且initcaller()
函数会产生错误。现在,通过引发异常,以python的方式报告此错误。但是
main.c
文件中的代码没有检查这个。我不是这方面的专家,但是在我的测试中,添加下面的代码initcaller()
似乎是有效的:程序的输出随后变为:
通过在
initcaller()
之前调用initquacker()
函数,模块名quacker
已经注册,因此在initcaller()
内完成的导入调用将检测到它已经加载,调用将成功。如果有人想知道它在Python 3中是如何工作的,下面是我作为一个Cython新手奋斗后的解决方案。
main.c
呼叫者.pyx
嘎嘎声.py
最后,这里是编译所有内容的Makefile:
相关问题 更多 >
编程相关推荐