Cython Compile Error: Python3 Compatibility

Cython Compile Error: Python3 Compatibility

我 运行宁 Python 3.4.4 :: Anaconda 4.0.0 (x86_64) OS X Yosemite。我的 Cython 版本是 0.23.4。我正在尝试将一些非常简单的 Cython 代码 test.pyx 嵌入到 C 代码 testcc.c 中。问题是,如果我使用 python2.7-config 那么一切正常(Python 2.7 是 OS X 上的内置版本)。但是,如果我使用 python3.4-config,则会出现以下错误:

Undefined symbols for architecture x86_64:
  "_inittest", referenced from:
      _main in testcc-b22dcf.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我必须使用 Python3,因为我所有的其他代码都写在里面。请帮我解决这个问题。


以下是我的源文件:

test.pyx:

cdef public void pythonAdd(int[] a):
    a[1] = 5
    a[0] = 4

testcc.c:

#include "Python.h"
#include "test.h"
#include <math.h>
#include <stdio.h>

int main(int argc, char **argv) {
    Py_Initialize();
    inittest();
    int a [2] = {0 , 0};
    pythonAdd(a);
    printf("fist: %d, second: %d", a[0], a[1]);
    Py_Finalize();
    return 0;
}

并使用以下 setup.py:

编译这两个文件
from distutils.core import setup, Extension
from Cython.Build import cythonize

ext = Extension("testc", sources=["test.pyx"])

setup(name="testc", ext_modules=cythonize(ext))

下面是我编译那些c文件的命令:

ldflags:=$(shell $(python3.4-config) --ldflags)
cflags:=$(shell $(python3.4-config) --cflags)
python setup.py build_ext --inplace
cython test.pyx
gcc $(cflags) $(ldflags) test.c testcc.c -o cysvm.out

更新:

我按照 Jim 的建议将 inittest() 更改为 PyInit_test()。代码编译成功。但是,当我 运行 ./cysvm.out 时,出现了以下错误:

./cysvm.out
Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Fatal Python error: Py_Initialize: unable to load the file system codec
ImportError: No module named 'encodings'

Current thread 0x00007fff772f5300 (most recent call first):

更新

我通过在 c 代码中的 Py_Initialize(); 之前添加以下行解决了这个问题:

Py_SetPythonHome(L"/PATH/to/python3");

这可能是因为在 Python 3.x 中,模块的初始化不是通过调用 init<module_name> 而是通过 PyInit_<module_name> 执行的(参见 PEP 3121).因此,如果您链​​接 Python 3.x 并通过 3.x 执行,您需要更改初始化调用。

简而言之,将初始化模块的调用更改为:

inittest();

收件人:

PyInit_test();

然后重新编译,应该可以解决问题。


至于你的第二个问题,除了使用 Py_SetPythonHome 之外的替代解决方案是在编译之前设置 PYTHONHOME to the output of python3.4-config --exec-prefix (or sys.exec_prefix)。