强制执行扩展加载顺序
Enforcing the order of extension loading
我有两个 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 加载扩展时将调用此函数。
我的猜测是,由于 OS 知道 a.so 依赖于 b.so,当 python 时系统加载 b(而不是 python) ] 仅请求 a.so。然而调用模块初始化函数是 python 的责任,而 python 不知道 a 依赖于 b,所以 OS 只加载 b 而没有初始化。在 import b
上,当 python 实际调用模块初始化函数时,它会产生不同的 PyTypeObject。
如果解决方案依赖于平台,我的项目目前在 linux (archlinux) 上 运行。
您似乎链接 a
到 b
以导入 b
定义的类型。不要这样做。
相反,像导入任何其他 Python 模块一样导入 b
。换句话说,对 b
的依赖应该完全由 Python 二进制文件处理,而不是由 OS 的动态库加载结构处理。
使用C-API import functions导入b
。到那时, 如何导入 b
应该无关紧要;从那时起,它只是一堆 Python 个对象。
这并不是说 b
不能为那些对象生成 C 级 API(NumPy 也这样做),你只需要确保它是 Python 加载扩展,而不是你的库。顺便说一句,NumPy 定义了为您导入的辅助函数,请参阅 the import_umath()
code generator 示例。
我有两个 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 加载扩展时将调用此函数。
我的猜测是,由于 OS 知道 a.so 依赖于 b.so,当 python 时系统加载 b(而不是 python) ] 仅请求 a.so。然而调用模块初始化函数是 python 的责任,而 python 不知道 a 依赖于 b,所以 OS 只加载 b 而没有初始化。在 import b
上,当 python 实际调用模块初始化函数时,它会产生不同的 PyTypeObject。
如果解决方案依赖于平台,我的项目目前在 linux (archlinux) 上 运行。
您似乎链接 a
到 b
以导入 b
定义的类型。不要这样做。
相反,像导入任何其他 Python 模块一样导入 b
。换句话说,对 b
的依赖应该完全由 Python 二进制文件处理,而不是由 OS 的动态库加载结构处理。
使用C-API import functions导入b
。到那时, 如何导入 b
应该无关紧要;从那时起,它只是一堆 Python 个对象。
这并不是说 b
不能为那些对象生成 C 级 API(NumPy 也这样做),你只需要确保它是 Python 加载扩展,而不是你的库。顺便说一句,NumPy 定义了为您导入的辅助函数,请参阅 the import_umath()
code generator 示例。