C++中加载Python共享库时出现未定义符号

13

我一直在尝试运行我的一个项目,但遇到了问题。 经过很多调试,我已经缩小了问题的范围,但不知道如何继续。

一些背景:我正在使用C ++代码中的python脚本。 这在Python上有点记录,并且我设法在我的基本可执行文件中很好地运行它。包括 #include 和 -lpython2.6,一切都很出色。

然而,当从共享库(.so)运行此python脚本时,出现了困难。 此共享库由模拟系统(OpenRAVE)作为“模块”“加载”。 系统使用名为SendCommand的“模块”的虚拟方法与此模块进行交互。 然后,该模块启动boost :: thread,给python自己的线程,然后返回到模拟系统。 但是,当python开始导入其模块并因此加载其动态库时,它失败了,我认为是由于以下错误:

 ImportError: /usr/lib/python2.6/dist-packages/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct 

我已在可执行文件和共享库上运行了ldd,似乎没有区别。 我还在上面运行了nm -D文件,_Py_ZeroStruct确实未定义。 如果你们想要命令的打印输出,我很乐意提供。 任何建议将不胜感激,谢谢。

以下是完整的python错误:

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 

导入错误:/usr/lib/python2.6/dist-packages/numpy/core/multiarray.so:未定义符号:_Py_ZeroStruct 回溯最近的调用: 文件“/home/constantin/workspace/OpenRAVE/src/grasp_behavior_2.py”,第3行,from openravepy import * 文件“/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/__init__.py”,第35行, openravepy_currentversion = loadlatest() 文件“/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/__init__.py”,第16行, return _loadversion('_openravepy_') 文件“/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/__init__.py”,第19行, mainpackage = __import__("openravepy", globals(), locals(), [targetname]) 文件“/home/constantin/workspace/rospackages/openrave/lib/python2.6/site-packages/openravepy/_openravepy_/__init__.py”,第29行, from openravepy_int import * 导入错误:numpy.core.multiarray无法导入
4个回答

10

我的应用程序也遇到了同样的问题,我使用了解除python与可执行文件之间的链接并解决了此问题。

设置如下:

可执行文件--链接-->库--动态加载-->插件--加载-->Python 解释器

避免导入错误的解决方案是更改以RTLD_GLOBAL方式加载插件的dlopen参数。

dlopen("plugin.so", RTLD_NOW | RTLD_GLOBAL)

这将使得这些符号对其他后加载的内容可用,例如其他插件或Python解释器。

然而,可能会出现符号冲突的情况,因为稍后的插件导出相同的符号。


2
解决方案是将Python 2.6库与我的可执行文件链接起来。
即使可执行文件没有调用Python,它也需要与Python库链接。我认为这是因为我的共享库没有将Python库的符号传递给可执行文件。如果有人能解释一下为什么我的可执行文件(在运行时加载我的动态库,而不进行链接)需要这些符号,那就太好了。
为了澄清,我的程序模型类似于: [我的可执行文件] -(动态加载)-> [我的共享库] -(调用并链接)-> [Python共享库]

0

请检查您的Python头文件和Python的运行时。看起来您混合使用了2.5和2.6版本。


0

在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

相关信息如下:

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 "[\r\n]" "" _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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接