我尝试从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找不到测试打印符号?
答案 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