我正在尝试从软件SDK获取提供的DLL文件并创建一个python包装器,以便将其与我的其余代码库集成。我在网上关注了不少指南,但仍然没有运气。
我目前使用的Python代码是:
from ctypes import *
from ctypes.wintypes import HWND
import os
class OptistarDLL(object):
dll_path = 'OSDS142MRT.dll'
with open(dll_path) as thefile:
pass
_dll = WinDLL(dll_path)
init_library = _dll['OSDS142M_Initialize']
init_library.restype = c_int
init_library.argtypes = (c_int, c_bool, HWND, c_bool, c_int)
class OpticstarControl(object):
def __init__(self):
err = OptistarDLL.init_library(c_int(0), c_bool(False), HWND(0), c_bool(False), c_int(0))
if err != 0:
raise Exception("Doom")
我正在使用的SDK文档将此作为函数的标题提供:
DLLDIR int OSDS142M_Initialize(int iModel, bool bOutVid, HWND hwOutVid, bool bStarView, int iRt);
示例PDF给出:
OSDS142M_Initialize(1, false, 0, true, 0);
初始化目前仅限我
ValueError: Procedure probably called with too many arguments (20 bytes in excess)
我已阅读但未了解WinDLL
vs CDLL
,并且当我更改为CDLL
时,DLL的加载失败。我在所有指南中都看到其中的标题为DLLEXPORT
而我的标题为DLLDIR
,我不知道这是否是一个问题。
有没有人有任何想法?
答案 0 :(得分:2)
根据问题中的信息,最可能的解释是DLL使用cdecl
而不是stdcall
。您对WinDLL
的使用与stdcall
DLL匹配。请改用CDLL
切换到cdecl
呼叫约定。
错误消息与此一致。调用约定之间的区别在于stdcall
具有被调用者堆栈清理并且cdecl
具有调用者清理。这些参数在堆栈上消耗20个字节,是5个大小为4的参数。而ctypes推送这些参数并期望被调用者清理堆栈。这不是因为它是cdecl
函数。
你对函数的调用是不必要的复杂。你可以写:
err = OptistarDLL.init_library(0, False, 0, False, 0)
请注意,您引用的示例调用会传递不同的参数。要匹配该电话,您可以写:
err = OptistarDLL.init_library(1, False, 0, True, 0)
您当然应该删除此代码:
with open(dll_path) as thefile:
pass
除了浪费时间之外没有任何其他目的。如果DLL不存在,您很快就会遇到失败。