Dynamic symbol lookup fails with statically embedded Python on Mac OS X

Question!

I'm building a Mac OS X application that is to embed Python. My application is technically a bundle (i.e. its main executable is MH_BUNDLE); it's a plug-in for another application. I'd like it to embed Python statically, but want to be able to load extensions dynamically.

I did the following: I included a whole library (-force_load path/to/libpython2.7.a), also reexported all Python symbols (-exported_symbol_list path/to/list), and added the -u _PyMac_Error, which I got using this linking advice. The bundle itself loads fine, all internal Python code appears to work, but it fails when it it tries to import a dynamic library (time.so) with the following message:

Traceback (most recent call last):
  ...
ImportError: dlopen(/<stripped>/time.so, 2): Symbol not found: _PyExc_OverflowError
  Referenced from: /<stripped>/time.so
  Expected in: dynamic lookup

This symbol is a part of Python API and it must be in my bundle already. I can check this:

nm -g Build/Debug/pyfm | grep _PyExc_OverflowError
00172884 D _PyExc_OverflowError
0019cde0 D _PyExc_OverflowError

(It's listed twice because I have two architectures, i386 and ppc).

The time.so doesn't reference anything, which, as I understand, is by design:

otool -L "/<stripped>/time.so"
/<stripped>/time.so (architecture ppc):
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.11)
/<stripped>/time.so (architecture i386):
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.11)

My problem appears to be similar to this, but it's the other way round: I do link Python statically, while the other poster linked it dynamically (an our platforms are different too). For him static linking solved the problem.

Why doesn't it find the symbol?

Update. I suspect it happens because the main app loads its plug-ins (and thus my bundle) with RTLD_LOCAL.



Answers

The “update” I made suggests it right: the main plug-in bundle is loaded locally (RTLD_LOCAL), so nobody can see any symbols there, unless using explicit dlopen followed by dlsym.

If it were Linux I could promote the bundle to the global namespace by dlopening it again with the RTLD_GLOBAL flag, but under Mac OS X this doesn't work. But Mac OS X nicely packs stuff into bundles, so I just made a dynamic library and put it into the plug-in bundle directory. The library loads automatically as RTLD_GLOBAL and all Python symbols are available.



This video can help you solving your question :)
By: admin