动态链接Python扩展(.pyd)到另一个扩展 [英] Dynamically Linking Python Extension (.pyd) to Another Extension
问题描述
Python扩展模块只是动态库,因此我认为可以将Python扩展动态链接到另一个。问题是在Windows Python上,扩展名被赋予 .pyd
扩展名,而不是 .dll
,所以我不能当我运行安装脚本时,让distutils链接到它们。 (我认为在UNIX上这不是问题,因为Python扩展名使用 .so
文件扩展名。)
Python Extension modules are just dynamic libraries, so I assume it's possible to dynamically link a Python extension to another. The problem is on Windows Python Extensions are are given the .pyd
extension instead of .dll
, so I can't get distutils to link to them when I run the setup script. (I don't think this is a problem on UNIX because Python extensions use the .so
file extension.)
假设我有一个扩展名 bar.pyd
,它需要链接到 foo.pyd
。基本上,我在设置脚本中所做的是:
Assume I have an extension bar.pyd
which needs to link to foo.pyd
. Basically, what I did in the setup script was:
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 ++和其他系统一起使用。
So far this isn't working. Is this even possible? I assume it is, but I haven't been able to find anything online. I'm using MinGW on Windows, but I would like this to work with different MSVC++ and on other systems as well.
编辑: ,我通过将在 foo
编译为<$时创建的目标文件( foo.o
)来解决了此问题。扩展名中的c $ c> extra_objects 选项(仅当我在 bar中定义所有
): foo
个符号的原型时,该选项才有效
Previously, I solved this problem by passing the object file (foo.o
) created when foo
was compiled to the extra_objects
option in the extension (this would only work if I defined prototypes of all foo
symbols in bar
):
bar = Extension("bar", sources=["bar.c"], extra_objects=["build/.../foo.o"]
这似乎没有是正确的解决方案,但它行得通。我不太了解动态链接,因此这可能是正确的方法。不过,感觉非常错误。
This didn't seem to be the right solution, but it worked. I don't understand dynamic linking that well, so this may be the right way to do it. It feels very wrong, though.
然后,我尝试将一些显式参数传递给gcc以使其编译导入库:
Then, I tried passing some explicit arguments to gcc to make it compile an import library:
foo = Extension("foo", sources=["foo.c"], extra_compile_args=["-Wl,--out-implib,foo.lib,--export-all-symbols"])
然后我将 bar
链接到新的导入库:
And then I linked bar
to the new import library:
bar = Extension("bar", libraries=["foo"], sources=["bar.c"])
此代码编译时没有任何抱怨,但是某些符号存在一些问题(特别是,我在全局中使用了一些<$ c foo
中的$ c> PyTypeObject 似乎已在 bar
中重新定义。我需要两个模块中的 PyTypeObject
都引用相同的定义。)
This compiled without complaint, but there were some issues with some of the symbols (specifically, I had a few global PyTypeObject
s in foo
that seemed to be redefined in bar
. I need the PyTypeObject
s in both modules refer to the same definition.).
编辑2: 因此,我提出了问题。在构建并链接导入库之后,函数符号可以正确导出,但是 PyTypeObject
被重新声明了。假设在 foo
中有一个 PyTypeOject Foo_Type
。我在 foo.h
中声明了它,它同时包含在 foo.c
和 bar中.c
:
Edit 2: So, I singled out the problem. Function symbols were exporting correctly after I built and linked against the import libraries, but the PyTypeObject
s were getting redeclared. Assume there was a PyTypeOject Foo_Type
in foo
. I declared it in foo.h
, which was included in both foo.c
and bar.c
:
PyTypeObject Foo_Type;
我将其取出,并将其放在 foo.c的顶部附近
:
I took that out, and put this near the top of foo.c
:
PyTypeObject __declspec(dllexport) Foo_Type;
,而这在 bar.c
:
PyTypeObject __declspec(dllimport) Foo_Type;
这解决了问题。然后,我可以在 foo
和 bar
中使用Foo_Type,它引用了Foo_Type的相同定义。问题是,这不适用于非Windows系统。我认为,如果只取出 __ declspec
,它在其他系统上也可以正常工作。
That fixed the problem. I could then use Foo_Type in both foo
and bar
and it referred to the same definition of Foo_Type. The problem is, this isn't going to work on non-Windows systems. I assume if I just take the __declspec
s out, it'll work fine on other systems.
推荐答案
如果您使用的是普通的Python 导入机制则无需链接其他扩展名。如果您要在另一个扩展中调用函数,大概是因为已经保留了头文件,那么您需要先从DLL生成一个导入lib,然后才能对其进行链接。
If you're using the normal Python import mechanisms then there's no need to link against the other extension. If you're calling functions within the other extension, presumably because you have gotten a hold on the header file, then you'll need to generate an import lib from the DLL before you can link against it.
这篇关于动态链接Python扩展(.pyd)到另一个扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!