所以我想通过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
  • Cython没有产生任何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_InitializePy_Finalize创建简单程序时,似乎不会发生。由于PYTHONPATH变量也用于填充sys.path python变量,因此上述解决方法会产生正确的结果。

    或者,您可以在Py_Intialize行下方,仅通过执行一些指定为字符串的python代码,向sys.path添加一个空字符串,如下所示:
    PyRun_SimpleString("import sys\nsys.path.insert(0,'')");
    

    重新编译后,只需运行./main就可以了。

    编辑

    实际上,如果您按照问题中的说明运行代码,将会看到发生了什么,这很有趣,因此无需重命名quacker.pyx文件。在这种情况下,initcaller()函数尝试导入quacker模块,但是由于不存在quacker.pyquacker.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/

    10-12 20:26