我有两个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)上运行。
答案 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作为示例。