动态链接Python扩展(.pyd)到另一个扩展 [英] Dynamically Linking Python Extension (.pyd) to Another Extension

查看:235
本文介绍了动态链接Python扩展(.pyd)到另一个扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 PyTypeObjects in foo that seemed to be redefined in bar. I need the PyTypeObjects 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 PyTypeObjects 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 __declspecs 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆