Undefined symbol when importing cythonized c++ code

I tried to call c++ code from python, using cython in this minimal(ish) example:

# setup.py
import numpy as np
import glob
from distutils.core import setup
from Cython.Distutils import build_ext
from distutils.core import setup
from 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=['textcpp.cpp'],
    #extra_compile_args=['-fopenmp', '-O3', '-ffast-math'],
    include_dirs = [np.get_include(), '.'],
    #extra_link_args=['-fopenmp']
  )
)
# pytest.py
from __future__ import division
import os
import time
import numpy as np
import scipy.sparse
from _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++ at work.n";
}

Then I ‘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 it 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’ is valid for C/ObjC but not for C++ [enabled by 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’ is valid for C/ObjC but not for C++ [enabled by default]

### !!!! The next statement shows that the `testcpp.cpp` file should be compiled and linked into `_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 I run this (from my homedirectory, and not the project directory, to make sure the installed version is used), the dynamic linker can’t find the 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>
    from _pytest import pyprint
ImportError: .../lib/python3.4/site-packages/_pytest.cpython-34m.so: undefined symbol: testprint

The … marks the location of the python 3 virtual environment. Notice that if I inspect the .so, the testprint symbol is found:

$ nm .../lib/python3.4/site-packages/_pytest.cpython-34m.so  | grep testprint
                 U testprint
0000000000001e60 T _Z9testprintv

Why is the testprint symbol not found by python 3?


Source: c++

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.