2011-11-28 123 views
11

我一直在試圖讓我的項目運行,但我遇到了麻煩。經過很多調試,我已經縮小了問題範圍,但不知道如何繼續。加載Python共享庫時C++中的未定義符號

一些背景知識,我在C++代碼中使用python腳本。這在Python上有所記錄,我設法讓它在我的基本可執行文件中運行得很好。 #include和-lpython2.6,一切都很棒。

但是,從共享庫(.so)運行此python腳本時出現困難。該共享庫由仿真系統(OpenRAVE)「加載」爲「模塊」。系統使用稱爲SendCommand的「模塊」的虛擬方法與此模塊交互。模塊然後啓動一個boost :: thread,給python自己的線程,然後返回到模擬系統。然而,當蟒蛇開始導入它的模塊,因此加載其動態庫失敗,我下面的錯誤承擔因:

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

我已經在我的可執行文件和共享庫運行LDD,有沒有一些人是一個區別。我也在上面的文件上運行nm -D,_Py_ZeroStruct確實沒有定義。如果你們想印出命令,我很樂意提供這些命令。任何意見將不勝感激,謝謝。

以下是完整的蟒蛇錯誤:

 
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 

回答

2

該解決方案還將python2.6庫與我的可執行文件鏈接起來。

儘管可執行文件沒有進行python調用,但它需要與python庫鏈接。我假設它是因爲我的共享庫不會將python庫的符號傳遞給可執行文件。如果任何人都可以解釋爲什麼我的可執行文件(它在運行時加載我的動態庫,而沒有鏈接)需要這些符號,那就太好了。

爲了澄清,我的程序模型是一樣的東西: [我的可執行文件] - (動態加載) - > [我的共享資源庫] - (呼叫和連接帶) - > [Python的共享庫]

0

檢查你的Python-header和Python的運行時間。看起來你有2.5和2.6版本的混合。

0

有在openrave展示瞭如何構建使用升壓蟒蛇,而無需C++共享對象的示例應用程序知道這一點:

http://openrave.org/en/coreapihtml/orpythonbinding_8cpp-example.html

搜索在cmake的文件「蟒蛇」在這裏:

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

我遇到了同樣的問題,我的應用程序和解決它沒有蟒蛇鏈接到可執行文件。

的設置如下:

可執行 - 鏈接 - >庫 - 動態負載 - >插件 - 負載 - > python解釋

的避免導入錯誤的解決方案是改變插件加載到RTLD_GLOBAL的dlopen參數。

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

這使符號可用於後來加載的其他東西,即其他插件或python解釋器。

但是,可以發生符號衝突,因爲插件稍後會導出相同的符號。