在Mac OS X上,静态嵌入Python时动态符号查找失败

3 投票
1 回答
1888 浏览
提问于 2025-04-16 07:09

我正在开发一个Mac OS X应用程序,里面要嵌入Python。我的应用程序实际上是一个包(也就是它的主执行文件是MH_BUNDLE);它是另一个应用程序的插件。我希望能静态嵌入Python,但又想动态加载扩展。

我做了以下操作:我包含了整个库(-force_load path/to/libpython2.7.a),还重新导出了所有Python符号(-exported_symbol_list path/to/list),并添加了-u _PyMac_Error,这个是我根据这篇链接建议得到的。包本身加载得很好,所有内部的Python代码似乎都能正常工作,但当它尝试导入一个动态库(time.so)时,就出现了以下错误信息:

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

这个符号是Python API的一部分,应该已经在我的包里了。我可以检查一下:

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

(它列了两次,因为我有两种架构,i386和ppc)。

这个time.so没有引用任何东西,我理解这是故意的设计:

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)

我的问题似乎和这个类似,但正好相反:我链接的是静态Python,而另一个帖子里的人链接的是动态(而且我们的平台也不同)。对他来说,静态链接解决了问题。

为什么找不到这个符号呢?

更新。 我怀疑这是因为主应用程序用RTLD_LOCAL加载它的插件(也就是我的包)。

1 个回答

1

我所做的“更新”表明是正确的:主要的插件包是本地加载的(RTLD_LOCAL),所以其他人看不到里面的任何符号,除非使用明确的 dlopen 然后再用 dlsym

如果是在Linux上,我可以通过再次使用 dlopen 并加上 RTLD_GLOBAL 标志,把这个包提升到全局命名空间,但在Mac OS X上这样做是不行的。不过,Mac OS X会把东西很好地打包,所以我只需制作一个动态库,并把它放到插件包目录里。这个库会自动以 RTLD_GLOBAL 加载,这样所有的Python符号就都可以用了。

撰写回答