使用Python中的DLL(使用ctypes),无法正常工作

3
我正在尝试编写一个DLL,可以在Python (2.7)中导入它,但是我很难 "让它正常工作"。 当我使用WinDLL()windll.LoadLibrary()在Python中加载库,并测试导出的函数时,输出为空。 如果我向TestFunction()添加参数,它会引发ValueError,并指出可能有太多参数(实际上不是这样)。
from ctypes import *

x = windll.LoadLibrary('./pymod.dll')
print x.TestFunction(123) #Should return 123.

main.h:

#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#define DLL_EXPORT __declspec(dllexport)    

#ifdef __cplusplus
extern "C"
{
#endif

int DLL_EXPORT TestFunction(int data);

#ifdef __cplusplus
}
#endif

#endif

以及 main.cpp:

#include "main.h"

int DLL_EXPORT TestFunction(int x = 0) {
    return x;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    switch (fdwReason){
        case DLL_PROCESS_ATTACH:
            break;
        case DLL_PROCESS_DETACH:
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
    }
    return TRUE;
}

解决方案:问题出在调用约定上。


我对你的问题/困难没有直接的答案,但如果你想制作Python模块,我会推荐使用Boost.Python。只是一个想法。 - DubyaDubyaDubyaDot
你能复制粘贴出具体的错误吗?我认为它应该指定多余/缺失字节数量。 - Michał Górny
确切的错误是 ValueError:可能使用过多参数调用过程(超出4个字节) - b0bz
你可以使用我的答案:https://dev59.com/12sz5IYBdhLWcg3w5ME0#13167362 - Reza Ebrahimi
为什么是"./pymod.dll"?它是Windows、Linux还是Cygwin? - MarioVilas
1个回答

6

我猜测您可能使用的调用约定与您的Python所假设的不同。

int DLL_EXPORT TestFunction(int data);

那段声明可能意味着将使用cdecl调用约定;而使用windll会让Python相信应该使用stdcall约定。这有效地改变了传递参数的方式,因此使Python相信您已经传递了错误数量的参数。在ctypes文档中有注明。
如果是这种情况,你可以进行以下任一操作:
  1. 在C代码中更改调用约定为stdcall(用于Windows系统DLL)。如果您使用MSVC,则可以查阅开发DLL的文档;
  2. 将Python代码所期望的调用约定更改为cdecl。这可以通过使用cdll来完成,而不是使用windll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接