执行扩展加载的顺序

时间:2018-01-13 17:24:26

标签: python shared-libraries

我有两个python扩展(动态库),例如a.so和b.so.在这两者中,a.so依赖于b.so,特别是它使用b.so。

中定义的类型

在python中,我可以放心地做到

import b
import a
# work

但是当我做的时候

import a
import b

导入正常,但在运行代码时,它会报告a中的b.the_type类型不是b中的b.the_type。仔细检查gdb,我发现a.so和b.so中该类型的PyTypeObject有两个不同的地址(和不同的refcnt)。

我的问题是如何强制执行加载订单,或确保两种方式都有效。

为了让那些熟悉共享库而不是python的人能够帮助我,这里有一些额外的信息。在python扩展中,python类型本质上是一个唯一的全局变量,它在其模块(.so文件)中初始化。类型必须在可以使用之前进行初始化(这可以通过调用python API来完成)。这些必需的初始化包含在具有特定名称的特定函数中。 Python将在加载扩展时调用此函数。

我的猜测是,因为操作系统知道a.so依赖于b.so,所以当python只请求a.so时,系统会加载b(而不是python)。然而,python负责调用模块初始化函数而python不知道取决于b,所以OS只加载b而不进行初始化。在import b上,当python实际调用模块初始化函数时,它会产生不同的PyTypeObject。

如果解决方案依赖于平台,我的项目当前正在linux(archlinux)上运行。

1 个答案:

答案 0 :(得分:0)

您似乎已将 a链接到b以导入b类型定义。不要这样做。

相反,导入b就像您使用任何其他Python模块一样。换句话说,对b的依赖应该完全由Python二进制文件处理,而不是由操作系统的动态库加载结构处理。

使用C-API import functions导入b。那时无关紧要如何导入b;从那时起,它只是一堆Python对象。

并不是说b无法为这些对象生成C级API(NumPy也这样做),您只需要确保加载的是Python扩展名,而不是你的图书馆。顺便提一下,NumPy定义了为您进行导入的辅助函数,请参阅the import_umath() code generator作为示例。