spacegoing spacegoing - 5 months ago 50
Python Question

Cython Compile Error: Python3 Compatibility

I am running

Python 3.4.4 :: Anaconda 4.0.0 (x86_64)
on
OS X Yosemite
. My Cython's version is
0.23.4
. I'm trying to embed some very trivial Cython code
test.pyx
into C code
testcc.c
. The problem is, if I use
python2.7-config
then everything works well (Python 2.7 is the built-in version on OS X). However if I use
python3.4-config
the following errors raised:

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)


I have to use Python3 since all my other codes are written in it. Please help me solve this problem.




The following are my source files:

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;
}


And Compiling those two files using following
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))


The following is the command I compile those c files:

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





Update:

I changed the
inittest()
to
PyInit_test()
as Jim suggested. The code compiles successfully. However when I run
./cysvm.out
the following errors occured:

./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):


Update



I solved this by adding the following line before
Py_Initialize();
in my
c
code:

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

Jim Jim
Answer

This is probably due to the fact that in Python 3.x initialization of modules is not performed by calling init<module_name> but rather with PyInit_<module_name> (See PEP 3121). So, if you are linking with Python 3.x and executing via 3.x you need to change the initialization call.

In short, changing the call that initializes the module from:

inittest();

To:

PyInit_test();

and recompiling, should do the trick.