【发布时间】:2010-07-17 01:01:38
【问题描述】:
Python 扩展模块只是动态库,所以我认为可以将 Python 扩展动态链接到另一个。问题在于 Windows Python 扩展被赋予.pyd 扩展而不是.dll,所以当我运行安装脚本时,我无法让 distutils 链接到它们。 (我认为这在 UNIX 上不是问题,因为 Python 扩展使用 .so 文件扩展名。)
假设我有一个扩展名bar.pyd,它需要链接到foo.pyd。基本上,我在设置脚本中所做的是:
from distutils.core import setup, Extension
foo = Extension("foo", sources=["foo.c"])
bar = Extension("bar", libraries=["foo"], sources=["bar.c"])
setup(ext_modules=[foo, bar])
到目前为止,这不起作用。这甚至可能吗?我认为是,但我一直无法在网上找到任何东西。我在 Windows 上使用 MinGW,但我希望它可以与不同的 MSVC++ 以及其他系统一起使用。
编辑: 以前,我通过将编译 foo 时创建的目标文件 (foo.o) 传递给扩展中的 extra_objects 选项来解决这个问题(这只有在我在bar中定义了所有foo符号的原型):
bar = Extension("bar", sources=["bar.c"], extra_objects=["build/.../foo.o"]
这似乎不是正确的解决方案,但它确实有效。我不太了解动态链接,所以这可能是正确的方法。不过感觉很不对劲。
然后,我尝试将一些显式参数传递给 gcc 以使其编译导入库:
foo = Extension("foo", sources=["foo.c"], extra_compile_args=["-Wl,--out-implib,foo.lib,--export-all-symbols"])
然后我将bar 链接到新的导入库:
bar = Extension("bar", libraries=["foo"], sources=["bar.c"])
编译时没有抱怨,但某些符号存在一些问题(具体来说,我在 foo 中有一些全局 PyTypeObjects,似乎在 bar 中重新定义。我需要 PyTypeObject两个模块中的 s 引用相同的定义。)。
编辑 2: 所以,我挑出了问题。在我构建并链接到导入库后,函数符号正确导出,但 PyTypeObjects 正在重新声明。假设foo 中有一个PyTypeOject Foo_Type。我在foo.h中声明了它,它包含在foo.c和bar.c中:
PyTypeObject Foo_Type;
我把它拿出来,放在foo.c的顶部附近:
PyTypeObject __declspec(dllexport) Foo_Type;
这在bar.c的顶部附近:
PyTypeObject __declspec(dllimport) Foo_Type;
这解决了问题。然后我可以在foo 和bar 中使用Foo_Type,它引用了Foo_Type 的相同定义。问题是,这不适用于非 Windows 系统。我想如果我只是把__declspecs 拿出来,它会在其他系统上正常工作。
【问题讨论】:
标签: python distutils dynamic-linking