I have a .dll I'm trying to access using ctypes. The header for the .dll looks like this:
typedef void* CMS_HANDLE;
CMS_HANDLE WINAPI cmsOpen( int nDeviceID , int nComType);
BOOL WINAPI cmsClose(CMS_HANDLE hCms);
My python code looks like this:
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)
It does the dll.cmsOpen correctly and returns a value. However, it doesn't like the value I pass into 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
I'm sure I'm just doing something dumb with the handle. Any ideas? (I have C-code that works with this .dll)
The problem is on 64-bit Python, handles are 64-bit, but ctypes assumes return types are c_int
(32-bit) if not specifically defined, so the cmsOpen
return value is already truncated when you put it into a c_void_p
.
What is always good practice, is to fully define both .argtypes
and .restype
for each function you use. This will convert parameters correctly, and provide error checking if passed incorrect or wrong number of arguments:
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)