导入cythonized c ++代码时未定义的符号

时间:2015-07-02 08:41:43

标签: c++ python-3.x cython

我尝试从python中调用c ++代码,在这个最小(ish)示例中使用cython:

# 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=['testcpp.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";
}

然后我编译&#39;这些:

#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

但是,当我运行它(从我的homedirectory而不是项目目录,以确保使用已安装的版本)时,动态链接器无法找到测试打印符号:

$ 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

...标记了python 3虚拟环境的位置。请注意,如果我检查.so,则会找到testprint符号:

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

为什么python 3找不到测试打印符号?

1 个答案:

答案 0 :(得分:0)

除了沮丧之外,我找到了解决方案。因此_pytext.pyx被处理为_pytest.cpp,在预处理(-E开关为g ++)之后,声明:

extern "C" void testprint(void);

这是这个cython声明的结果:

cdef extern void testprint ()

基本上它声明了C function(带有符号testprint),而{。1}}(带有符号C++ function)则在.so文件中定义。以来 _Z9testprintv!= testprint我们收到了_Z9testprintv

那么我们该如何解决这个问题呢?我对最佳解决方案是什么一无所知,但这似乎有效:

undefined symbol: testprint