在Python中编译并与C DLL接口可以在Unix上工作,但不能在Windows上工作。正确的方法是什么?

2024-05-13 11:19:24 发布

您现在位置:Python中文网/ 问答频道 /正文

所以,我有以下文件:

添加一个.c

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

然后通过GCC 7.2.0的Windows安装编译成DLL(我也尝试使用英特尔C++编译器,在将函数更改为^ {CD1>}之后,但这不会改变当我尝试将其加载到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系统上实现这一点,并且在该平台上将cdll与Python接口也没有问题。然而,搬到Windows上,我觉得我遗漏了一些东西。即使在不同的机器上尝试所有这些,我仍然无法访问我编写的函数。你知道吗

我觉得我错过了什么。我做错什么了?你知道吗


Tags: 对象方法函数编译器windowsctypeslongint
2条回答

经过一番摆弄,我知道发生了什么事。你知道吗

函数确实已经正确地编写,正确地编译成DLL,并且ctypes.CDLL文件对象创建正确。你知道吗

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

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

尝试导出函数:

#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);

相关问题 更多 >