【问题标题】:Dynamically Linking Python Extension (.pyd) to Another Extension将 Python 扩展 (.pyd) 动态链接到另一个扩展
【发布时间】: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.cbar.c中:

PyTypeObject Foo_Type;

我把它拿出来,放在foo.c的顶部附近:

PyTypeObject __declspec(dllexport) Foo_Type;

这在bar.c的顶部附近:

PyTypeObject __declspec(dllimport) Foo_Type;

这解决了问题。然后我可以在foobar 中使用Foo_Type,它引用了Foo_Type 的相同定义。问题是,这不适用于非 Windows 系统。我想如果我只是把__declspecs 拿出来,它会在其他系统上正常工作。

【问题讨论】:

    标签: python distutils dynamic-linking


    【解决方案1】:

    如果您使用的是普通 Python import mechanisms,则无需链接到其他扩展。如果你在另一个扩展中调用函数,大概是因为你已经获得了头文件,那么你需要先从 DLL 生成一个导入库,然后才能链接它。

    【讨论】:

    • 这两个扩展模块都是我项目的一部分,所以我想在它们之间进行链接,而不是使用 Python 导入机制。不过,我对此很陌生,所以我不太确定如何生成导入库。你能解释一下吗?
    【解决方案2】:
    from distutils.core import Extension as cExtension
    from pyd.support import setup, Extension
    
    module1 = Extension("x", sources = ['xclass.c'])
    module2 = Extension("y", sources = ['hello.d'], build_deimos=True)
    
    setup(
        name = "x",
        version = '1.0',
        description = "eat a taco",
        ext_modules = [
            module1,
            module2
        ]
    );
    

    来自:http://pyd.readthedocs.io/en/latest/distutils.html

    【讨论】:

    • 这与D编程语言无关。
    • pyd 在问题标题中指的是“python dll”,而不是“Python 的 D 编程语言”
    猜你喜欢
    • 2012-01-05
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    相关资源
    最近更新 更多