首页 > 解决方案 > 从使用 Python ctypes 调用的 .dll 返回句柄

问题描述

我正在尝试通过制造商和 Ctypes 提供的 .dll 使用 Python 与示波器进行通信。我是 C 的新手,所以我可能会遗漏一些明显的东西,但我似乎无法正确调用更复杂的函数。

我可以访问 .dll 文件和 .h 文件。

.h 文件的摘录:

typedef long ScHandle;

...

int ScOpenInstrument(int wire, char* address, ScHandle* rHndl);

我的python代码:

import ctypes

lib = ctypes.WinDLL("ScAPI.dll")

# Define types
ScHandle = ctypes.c_long

# Define function argument types
lib.ScOpenInstrument.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(ScHandle)]
lib.ScStart.argtypes = [ScHandle]

# Init library
ret = lib.ScInit()

# Open instrument
wire = ctypes.c_int(7)
addr = ctypes.c_char_p("91SB21329".encode("utf-8"))
handle = ScHandle(0)

ret = lib.ScOpenInstrument(wire, addr, ctypes.byref(handle))

该函数应该向示波器返回一个句柄,但我得到了错误:

ValueError:过程可能调用了太多参数(超过 12 个字节)

标签: pythondllctypes

解决方案


根据[Python 3.Docs]:ctypes - Calling functions重点是我的):

...

当您stdcall使用调用约定调用函数时会引发相同的异常cdecl,反之亦然

>>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>>

>>> windll.msvcrt.printf(b"spam") # doctest: +WINDOWS
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>

要找出正确的调用约定,您必须查看 C 头文件或要调用的函数的文档。

...

似乎您使用了错误的调用约定(此错误还表明您正在运行32bit Python)。要更正它,请使用:

lib = ctypes.CDLL("ScAPI.dll")

此外,您可以缩短addr初始化:

addr = ctypes.c_char_p(b"91SB21329")

推荐阅读