2011-11-28 14 views
11

Ho cercato di far funzionare un mio progetto ma ho avuto dei problemi. Dopo molte operazioni di debug, ho ristretto il problema ma non ho idea di come procedere.Simbolo non definito in C++ durante il caricamento di una libreria condivisa Python

Qualche sfondo, sto usando uno script python all'interno del codice C++. Questo è un po 'documentato su Python, e sono riuscito a farlo funzionare molto bene nel mio eseguibile di base. #include e un -lpython2.6 e tutto era grandioso.

Tuttavia, è stata rilevata una difficoltà durante l'esecuzione di questo script python da una libreria condivisa (.so). Questa libreria condivisa è "caricata" come "modulo" da un sistema di simulazione (OpenRAVE). Il sistema interagisce con questo modulo utilizzando un metodo virtuale per "moduli" chiamato SendCommand. Il modulo avvia quindi un boost :: thread, dando a python il proprio thread e ritorna al sistema di simulazione. Tuttavia, quando inizia l'importazione pitone suoi moduli e quindi di caricare le sue librerie dinamiche non riesce, presumo a causa del seguente errore:

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

Ho eseguito ldd sul mio eseguibile e la libreria condivisa, non ci fa un po 'di fare la differenza Ho anche eseguito nm -D nel file sopra, _Py_ZeroStruct è effettivamente indefinito. Se voi ragazzi voleste la stampa dei comandi sarei lieto di fornirli. Qualsiasi consiglio sarebbe molto apprezzato, grazie.

Ecco l'errore pitone completo:

 
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 

risposta

2

La soluzione era il collegamento della libreria python2.6 con il mio eseguibile.

Anche se l'eseguibile non ha effettuato chiamate python, doveva essere collegato alla libreria python. Presumo che sia perché la mia libreria condivisa non passa i simboli della libreria Python attraverso l'eseguibile. Se qualcuno potesse spiegare perché il mio eseguibile (che carica la mia libreria dinamica in fase di runtime, senza collegamento) ha bisogno di quei simboli sarebbe fantastico.

Per chiarezza, il mio modello programma è qualcosa di simile: [My eseguibile] - (carica dinamicamente) -> [My Shared Library] - (chiamate e collegamenti con) -> [Python condiviso Biblioteca]

0

Controlla la tua python-header e runtime di Python. Sembra che tu abbia un mix di versioni 2.5 e 2.6.

0

c'è un esempio in openrave che mostra come costruire C++ oggetti condivisi che utilizzano spinta python senza avere l'applicazione sapere a questo proposito:

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

ricerca per "python" nel file cmake qui:

https://openrave.svn.sourceforge.net/svnroot/openrave/trunk/src/cppexamples/CMakeLists.txt

le informazioni pertinenti è:

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

ho sperimentato lo stesso problema con la mia domanda e risolto senza collegamento python al file eseguibile.

La messa a punto è il seguente:

eseguibile - link -> Libreria - dinamicamente i carichi -> Plugin - carichi -> interprete Python

Il soluzione per evitare che ImportErrors fosse modificare i parametri di dlopen, con cui il plugin è stato caricato su RTLD_GLOBAL.

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

Questo rende i simboli disponibili per altre cose caricati in seguito, vale a dire altri plugin o l'interprete Python.

Tuttavia, è possibile che si verifichino conflitti di simboli, poiché un plug-in in seguito esporta gli stessi simboli.