【问题标题】:Undefined Symbol in C++ When Loading a Python Shared Library加载 Python 共享库时 C++ 中的未定义符号
【发布时间】:2012-01-08 07:45:39
【问题描述】:

我一直试图让我的一个项目运行,但我遇到了麻烦。经过多次调试,我缩小了问题范围,但不知道如何进行。

一些背景知识,我在 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错误:

回溯(最近一次通话最后): 文件“/usr/lib/python2.6/dist-packages/numpy/__init__.py”,第 130 行,在 导入 add_newdocs 文件“/usr/lib/python2.6/dist-packages/numpy/add_newdocs.py”,第 9 行,在 从库导入 add_newdoc 文件“/usr/lib/python2.6/dist-packages/numpy/lib/__init__.py”,第 4 行,在 从 type_check 导入 * 文件“/usr/lib/python2.6/dist-packages/numpy/lib/type_check.py”,第 8 行,在 将 numpy.core.numeric 导入为 _nx 文件“/usr/lib/python2.6/dist-packages/numpy/core/__init__.py”,第 5 行,在 导入多数组 ImportError:/usr/lib/python2.6/dist-packages/numpy/core/multiarray.so:未定义符号:_Py_ZeroStruct 回溯(最近一次通话最后): 文件“/home/constantin/workspace/OpenRAVE/src/grasp_behavior_2.py”,第 3 行,在 从 openravepy 导入 * 文件“/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 行,在 loadlatest 返回 _loadversion('_openravepy_') _loadversion 中的文件“/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 行,在 从 openravepy_int 导入 * ImportError:numpy.core.multiarray 导入失败

【问题讨论】:

    标签: python shared-libraries undefined-symbol openrave


    【解决方案1】:

    检查您的 python-headers 和 python 的运行时。看起来您混合了 2.5 和 2.6 版本。

    【讨论】:

      【解决方案2】:

      解决方案也将 python2.6 库与我的可执行文件链接起来。

      即使可执行文件没有进行 python 调用,它也需要与 python 库链接。我假设它是因为我的共享库没有将 python 库的符号传递给可执行文件。如果有人能解释为什么我的可执行文件(在运行时加载我的动态库,没有链接)需要这些符号,那就太好了。

      为了澄清,我的程序模型类似于: [我的可执行文件] -(动态加载)-> [我的共享库] -(调用和链接)-> [Python 共享库]

      【讨论】:

        【解决方案3】:

        在 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()
        

        【讨论】:

          【解决方案4】:

          我的应用程序遇到了同样的问题,在没有将 python 链接到可执行文件的情况下解决了它。

          设置如下:

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

          避免 ImportErrors 的解决方案是更改 dlopen 的参数,使用该参数将插件加载到 RTLD_GLOBAL

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

          这使得符号可用于之后加载的其他内容,即其他插件或 python 解释器。

          但是,可能会发生符号冲突,因为插件稍后会导出相同的符号。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-14
            相关资源
            最近更新 更多