0

I wrote a C++ "python plugin" for an a non-python C++ application.
At some point, this plugin, which is a .so, initializes the python interpreter and opens a python console.
For convenience the "readline" module is then imported and we get this error:

ImportError: /usr/lib/python2.7/lib-dynload/readline.so: undefined symbol: PyOS_InputHook

The link command (generated by cmake) goes:

/usr/bin/c++ -fPIC -Wall -Wextra -O3 -DNDEBUG -Xlinker -export-dynamic -Wl,-fwhole-program /usr/lib/libpython2.7.a -shared -Wl,-soname,libMyplugin.so -o libMyplugin.so [sources] [qt libs] -lGLU -lGL -lX11 -lXext -lc -lc -lpython2.7 -Wl,-rpath,/src:/usr/local/Trolltech/Qt-4.8.4/lib:

nm libMyplugin.so gives the following python-related symbols:

                 U Py_Finalize
                 U Py_Initialize
00000000002114a8 B PyOS_InputHook
                 U PyRun_InteractiveLoopFlags
                 U PyRun_SimpleStringFlags

We observe that PyOS_InputHook is defined in the BSS section of the plugin. Yet, python's readline.so fails to find it.

The question is why, and how to fix it.

user2179288
  • 203
  • 2
  • 12
  • One possible explanation: when the main application loads the plugin with dlopen() it may use some flag RTLD_LOCAL intead of RTLD_GLOBAL. Then symbols would not be made available for the .so loaded subsequently (like readline.so). To be verified... – user2179288 Mar 23 '13 at 21:36
  • Actually, PyOS_InputHook was initially not present in libMyplugin.so, and it didn't work either. I added such a definition of this symbol in the plugin code source afterwards to see if it helped. It does not. – user2179288 Mar 23 '13 at 22:01

1 Answers1

0

The issue is with how the main application loads the plugin: it uses dlopen() without the flag RTLD_GLOBAL.
This implies that the symbols present in the plugin that are not currently needed (like PyOS_InputHook in this instance) are not resolved and will not be resolved for other shared libraries that will be loaded afterwards (like readline.so in this instance).

To fix this, the flag RTLD_GLOBAL should be used when loading the plugin.
If there is no control over the main application (as in this instance) and on how it uses dlopen(), it is still possible to "reload" the plugin from within the plugin itself using dlopen() with flags RTLD_NOLOAD | RTLD_GLOBAL, so as to resolve all previously unresolved symbols in the currently loaded library.

Doing this solves the issue.

user2179288
  • 203
  • 2
  • 12