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

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的参数,插件加载到RTLD_GLOBAL

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版本的混合。