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.
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 explicitdlopenfollowed bydlsym.If it were Linux I could promote the bundle to the global namespace by
dlopening it again with theRTLD_GLOBALflag, 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 asRTLD_GLOBALand all Python symbols are available.