Undefined Symbol in C++ When Loading a Python Shared Library
我一直试图让我的项目运行,但我遇到了麻烦。经过大量调试后,我已经缩小了问题但不知道如何继续。
一些背景,我在C ++代码中使用python脚本。这在Python上有所记录,我设法让它在我的基本可执行文件中运行得很好。 #include和-lpython2.6,一切都很棒。
但是,从共享库(.so)运行此python脚本时出现了困难。该共享库由模拟系统(OpenRAVE)"加载"为"模块"。系统使用名为SendCommand的"模块"的虚拟方法与此模块交互。然后该模块启动boost :: thread,为python提供自己的线程,并返回到模拟系统。但是,当python开始导入其模块并因此加载其动态库时,它会失败,我假设由于以下错误:
1 | ImportError: /usr/lib/python2.6/dist-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct |
我在我的可执行文件和共享库上运行了ldd,没有一些区别。我还在上面的文件上运行了nm -D,_Py_ZeroStruct确实是未定义的。如果你们想要打印命令,我很乐意提供它们。非常感谢任何建议,谢谢。
这是完整的python错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Traceback (most recent call last): File"/usr/lib/python2.6/dist-packages/numpy/__init__.py", line 130, in import add_newdocs File"/usr/lib/python2.6/dist-packages/numpy/add_newdocs.py", line 9, in from lib import add_newdoc File"/usr/lib/python2.6/dist-packages/numpy/lib/__init__.py", line 4, in from type_check import * File"/usr/lib/python2.6/dist-packages/numpy/lib/type_check.py", line 8, in import numpy.core.numeric as _nx File"/usr/lib/python2.6/dist-packages/numpy/core/__init__.py", line 5, in import multiarray ImportError: /usr/lib/python2.6/dist-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct Traceback (most recent call last): File"/home/constantin/workspace/OpenRAVE/src/grasp_behavior_2.py", line 3, in from openravepy import * File"/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/__init__.py", line 35, in openravepy_currentversion = loadlatest() File"/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/__init__.py", line 16, in loadlatest return _loadversion('_openravepy_') File"/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/__init__.py", line 19, in _loadversion mainpackage = __import__("openravepy", globals(), locals(), [targetname]) File"/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/_openravepy_/__init__.py", line 29, in from openravepy_int import * ImportError: numpy.core.multiarray failed to import |
我遇到了与我的应用程序相同的问题并解决了它而没有将python链接到可执行文件。
设置如下:
可执行文件--links - > library --dynamically-loads - > plugin --loads - > python interpreter
避免ImportErrors的解决方案是更改dlopen的参数,插件加载到
1 | dlopen("plugin.so", RTLD_NOW | RTLD_GLOBAL) |
这使符号可用于之后加载的其他内容,即其他插件或python解释器。
但是,可能会发生符号冲突,因为插件稍后会导出相同的符号。
解决方案是将python2.6库与我的可执行文件链接起来。
即使可执行文件没有进行python调用,它也需要与python库链接。我假设它是因为我的共享库没有将python库的符号传递给可执行文件。如果有人能解释为什么我的可执行文件(在运行时加载我的动态库,没有链接)需要这些符号,那就太好了。
为了澄清,我的程序模型类似于:
[我的可执行文件] - (动态加载) - > [我的共享库] - (调用和链接) - > [Python共享库]
openrave中有一个例子,它展示了如何构建使用boost python的C ++共享对象,而不需要应用程序知道它:
http://openrave.org/en/coreapihtml/orpythonbinding_8cpp-example.html
在cmake文件中搜索"python":
https://openrave.svn.sourceforge.net/svnroot/openrave/trunk/src/cppexamples/CMakeLists.txt
相关信息是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | if( Boost_PYTHON_FOUND AND Boost_THREAD_FOUND ) find_package(PythonLibs) if( PYTHONLIBS_FOUND OR PYTHON_LIBRARIES ) if( PYTHON_EXECUTABLE ) # get the site-packages directory execute_process( COMMAND ${PYTHON_EXECUTABLE} -c"from distutils.sysconfig import get_python_lib; print get_python_lib(1)" OUTPUT_VARIABLE _python_sitepackage RESULT_VARIABLE _python_failed) if( ${_python_failed} EQUAL 0 ) string(REGEX REPLACE"[ ]""" _python_sitepackage"${_python_sitepackage}") set(PYTHON_INCLUDE_PATH ${PYTHON_INCLUDE_PATH} ${_python_sitepackage}/numpy/core/include) else() message(STATUS"failed to get python site-package directory") endif() endif() include_directories(${PYTHON_INCLUDE_PATH} ${OpenRAVE_INCLUDE_DIRS}) add_library(orpythonbinding SHARED orpythonbinding.cpp) target_link_libraries(orpythonbinding ${OpenRAVE_LIBRARIES} ${PYTHON_LIBRARIES} ${Boost_PYTHON_LIBRARY} ${Boost_THREAD_LIBRARY}) set_target_properties(orpythonbinding PROPERTIES PREFIX"" COMPILE_FLAGS"${OpenRAVE_CXX_FLAGS}") if( WIN32 ) set_target_properties(orpythonbinding PROPERTIES SUFFIX".pyd") endif() endif() endif() |
检查你的python-headers和python的运行时。看起来你有2.5和2.6版本的混合。