如何使用 c_void_p 作为句柄

How to use c_void_p as a handle

我有一个 .dll,我正在尝试使用 ctypes 访问。 .dll 的 header 如下所示:

typedef void* CMS_HANDLE;
CMS_HANDLE  WINAPI cmsOpen( int nDeviceID , int nComType);
BOOL        WINAPI cmsClose(CMS_HANDLE hCms);

我的 python 代码如下所示:

from ctypes import WinDLL, c_void_p, c_double, byref
dll = WinDLL("CMS_APIX64.dll")
handle = c_void_p(dll.cmsOpen(15, 3))
print(handle)
dll.cmsClose(handle)

它正确地 dll.cmsOpen 和 returns 一个值。但是,它不喜欢我传递给 dll.cmsClose():

的值
c_void_p(18446744072525716064)
Traceback (most recent call last):
  File "C:\Users\mjwilson\dev\Cms100-tool\cms100-tool.py", line 40, in <module>
    dll.cmsClose(handle)
OSError: exception: access violation reading 0xFFFFFFFFB9701A60

我确定我只是在用手柄做一些愚蠢的事情。有任何想法吗? (我有 C-code 适用于此 .dll)

问题出在 64 位 Python,句柄是 64 位,但 ctypes 假设 return 类型是 c_int(32 位),如果没有具体定义的话,所以当您将 cmsOpen return 值放入 c_void_p.

时,该值已被截断

什么是 always 好的做法,是为您使用的每个函数完全定义 .argtypes.restype。这将正确转换参数,并在传递不正确或错误数量的参数时提供错误检查:

from ctypes import *

dll = WinDLL("CMS_APIX64.dll")
dll.cmsOpen.argtypes = c_int,c_int
dll.cmsOpen.restype = c_void_p
dll.cmsClose.argtypes = c_void_p,
dll.cmsClose.restype = c_int

handle = dll.cmsOpen(15, 3)
print(handle)
dll.cmsClose(handle)