python 3.x - Undefined symbol when importing cythonized c++ code -
i tried call c++ code python, using cython in minimal(ish) example:
# setup.py import numpy np import glob distutils.core import setup cython.distutils import build_ext distutils.core import setup cython.build import cythonize setup( name = "pytest", version = "0.0.1", author = "herbert", #cmdclass = {'build_ext': build_ext}, py_modules = ['pytest'], ext_modules = cythonize( '_pytest.pyx', language="c++", sources=['testcpp.cpp'], #extra_compile_args=['-fopenmp', '-o3', '-ffast-math'], include_dirs = [np.get_include(), '.'], #extra_link_args=['-fopenmp'] ) )
# pytest.py __future__ import division import os import time import numpy np import scipy.sparse _pytest import pyprint pyprint()
# _pytest.pyx # distutils: language = c++ # distutils: sources = testcpp.cpp cimport cython cdef extern void testprint () @cython.boundscheck(false) def pyprint(): testprint()
#include <iostream> void testprint() { std::cout << "c++ @ work.\n"; }
then 'compile' these:
#removing possible left overs: $ rm -rf build/ __pycache__/ _pytest.cpp $ rm -rf ~/venv3/lib/python3.4/site-packages/{_pytest.cpython-34m.so,pytest*} $ python3 setup.py clean .../lib/python3.4/site-packages/cython/compiler/main.py:514: userwarning: got unknown compilation options, please remove: sources, include_dirs warnings.warn(message) compiling _pytest.pyx because changed. cythonizing _pytest.pyx running clean $ python3 setup.py install .../lib/python3.4/site-packages/cython/compiler/main.py:514: userwarning: got unknown compilation options, please remove: sources, include_dirs warnings.warn(message) running install running build running build_py creating build creating build/lib.linux-x86_64-3.4 copying pytest.py -> build/lib.linux-x86_64-3.4 running build_ext building '_pytest' extension creating build/temp.linux-x86_64-3.4 x86_64-linux-gnu-gcc -pthread -dndebug -g -fwrapv -o2 -wall -wstrict-prototypes -g -fstack-protector --param=ssp-buffer-size=4 -wformat -werror=format-security -d_fortify_source=2 -fpic -i.../include -i/usr/include/python3.4m -c _pytest.cpp -o build/temp.linux-x86_64-3.4/_pytest.o cc1plus: warning: command line option ‘-wstrict-prototypes’ valid c/objc not c++ [enabled default] x86_64-linux-gnu-gcc -pthread -dndebug -g -fwrapv -o2 -wall -wstrict-prototypes -g -fstack-protector --param=ssp-buffer-size=4 -wformat -werror=format-security -d_fortify_source=2 -fpic -i.../include -i/usr/include/python3.4m -c testcpp.cpp -o build/temp.linux-x86_64-3.4/testcpp.o cc1plus: warning: command line option ‘-wstrict-prototypes’ valid c/objc not c++ [enabled default] ### !!!! next statement shows `testcpp.cpp` file should compiled , linked `_pytest.cpython-34m.so`: x86_64-linux-gnu-g++ -pthread -shared -wl,-o1 -wl,-bsymbolic-functions -wl,-bsymbolic-functions -wl,-z,relro -wl,-bsymbolic-functions -wl,-z,relro -g -fstack-protector --param=ssp-buffer-size=4 -wformat -werror=format-security -d_fortify_source=2 build/temp.linux-x86_64-3.4/_pytest.o build/temp.linux-x86_64-3.4/testcpp.o -o build/lib.linux-x86_64-3.4/_pytest.cpython-34m.so running install_lib copying build/lib.linux-x86_64-3.4/pytest.py -> .../lib/python3.4/site-packages copying build/lib.linux-x86_64-3.4/_pytest.cpython-34m.so -> ..../lib/python3.4/site-packages running install_egg_info writing ..../lib/python3.4/site-packages/pytest-0.0.1.egg-info
however, when run (from homedirectory, , not project directory, make sure installed version used), dynamic linker can't find testprint symbol:
$ python3 -c 'import pytest;' traceback (most recent call last): file "<string>", line 1, in <module> file ".../lib/python3.4/site-packages/pytest.py", line 6, in <module> _pytest import pyprint importerror: .../lib/python3.4/site-packages/_pytest.cpython-34m.so: undefined symbol: testprint
the ... marks location of python 3 virtual environment. notice if inspect .so, testprint symbol found:
$ nm .../lib/python3.4/site-packages/_pytest.cpython-34m.so | grep testprint u testprint 0000000000001e60 t _z9testprintv
why testprint symbol not found python 3?
all frustration aside, found solution. _pytext.pyx
gets processed _pytest.cpp
, after preprocessing (-e switch in g++), declares:
extern "c" void testprint(void);
this result of cython statement:
cdef extern void testprint ()
basically declared c function
(with symbol testprint
), whereas c++ function
(with symbol _z9testprintv
) defined in .so file. since testprint
!= _z9testprintv
got undefined symbol: testprint
so how fix this? clueless best solution is, seems work:
cdef extern "testcpp.h": cdef void testprint ()
Comments
Post a Comment