Cython编译错误:Python3兼容性

时间:2016-06-13 13:09:51

标签: python cython anaconda

我正在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):

更新

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

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

1 个答案:

答案 0 :(得分:2)

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

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

inittest();

要:

PyInit_test();

并重新编译,应该做的伎俩。

至于您的第二个问题,除了使用Py_SetPythonHome之外的其他解决方案是在编译之前将PYTHONHOME设置为python3.4-config --exec-prefix(或sys.exec_prefix)的输出。