在Python中编译和连接C DLL可以在Unix上运行,但不能在Windows上运行.正确的方法是什么



因此,我有以下文件:

addone.c

long int addone(long int x){
return x+1;
}

然后通过GCC 7.2.0的windows安装将其编译成DLL(在将函数更改为extern "C" long int addone(long int x)后,我也尝试过使用英特尔C++编译器,但当我尝试将其加载到Python中时,这不会改变结果):

gcc -c addone.c
gcc -shared -o addone.dll addone.o

然后我尝试将其加载到python 3.6.7:中

import ctypes
_addone = ctypes.CDLL("addone.dll")

虽然我确实设法得到了CDLL对象,但它缺少函数"addone"。我尝试过使用ctypes.WinDLL()ctypes.windll.LoadLibrary方法导入C DLL,但它们都实现了相同的最终结果:我从ctypes中获得了一个没有公共方法的对象,并且没有任何私有方法(在Python对象中,而不是DLL中)似乎与addone函数相关。

只是为了再次检查我的编译器是否在做我期望的事情,我分解了生成的DLL,它看起来像一个典型的DLL。在内部,该功能甚至没有名字被篡改:

0000000530ce1030 <add_one>:
530ce1030:   55                      push   %rbp
530ce1031:   48 89 e5                mov    %rsp,%rbp
530ce1034:   48 89 4d 10             mov    %rcx,0x10(%rbp)
530ce1038:   48 8b 45 10             mov    0x10(%rbp),%rax
530ce103c:   48 83 c0 01             add    $0x1,%rax
530ce1040:   5d                      pop    %rbp
530ce1041:   c3                      retq
530ce1042:   90                      nop
<Everything between these two instructions is just more no-ops>
530ce104f:   90                      nop

我已经能够在Unix系统上实现这一点,并且在该平台上将C DLL与Python接口没有任何问题。然而,转到Windows时,我感觉自己错过了一些东西。即使在另一台机器上尝试所有这些,我仍然无法访问我编写的函数。

我觉得我错过了什么。我做错了什么?

尝试导出函数:

#include "addone.h"
EXPORT long int addone(long int x){
return x+1;
}

并制作头文件addone.h:

#define EXPORT __declspec(dllexport)
EXPORT long int addone(long int x);

经过一番摆弄,我明白了发生了什么

这个函数确实写得很正确,正确地编译成了DLL,还有ctypes。CDLL对象创建正确。

ctypes。CDLL对象没有立即"看到"函数名,因此它不在方法列表中。我所做的是忽略了这个方法不在对象的命名空间中的事实,我大胆地调用了_addone.addone(x)。这使对象意识到该函数在DLL中,并将其添加到名称空间中。

我怀疑ctypes中存在一些后端,调用函数会导致它检查库中是否真的存在该名称。也许这是为了防止命名空间被编译器放入DLL中的各种其他函数弄得一团糟。

最新更新