Dynamic symbol lookup fails with statically embedded Python on Mac OS X
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 othe开发者_如何学Gor 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 explicit dlopen
followed by dlsym
.
If it were Linux I could promote the bundle to the global namespace by dlopen
ing 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.
精彩评论