Python 3.x - 导入密码化 C++ 代码时未定义的符号

python 3.x - Undefined symbol when importing cythonized c++ code

本文关键字:代码 未定义 符号 C++ 导入 密码 Python      更新时间:2023-10-16

我试图从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";
}

然后我"编译"这些:

#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

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

$ 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,则会找到测试打印符号:

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

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

抛开

所有的挫败感,我找到了解决方案。因此,_pytext.pyx被处理为 _pytest.cpp ,经过预处理(g++ 中的 -E 开关(,声明:

extern "C" void testprint(void);

这是这个cython声明的结果:

cdef extern void testprint ()

基本上它声明了一个C function(符号testprint(,而C++ function(符号_Z9testprintv(是在.so文件中定义的。因为 testprint != _Z9testprintv我们得到了一个undefined symbol: testprint

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

cdef extern from "testcpp.h":
  cdef void testprint ()
相关文章: