I have a GetImageData function in a DLL:
int GetImageData ( const char * name , int ID , const char * strLibPath , int Lvl , int rbeg , int rend , int cbeg , int cend , int ZLayer , unsigned char * ImgBuffer );
in Python I import this DLL and establish the variables:
import ctypes,numpy
from ctypes import *
Wlib = ctypes.WinDLL('C:\\...\\Wsl.dll')
GetImage=Wlib["GetImage"]
name =c_char_p(fname)
ID =c_int(0)
strLibPath=c_char_p(LibPath)
Lvl =c_int(0)
rbeg =c_int(100)
rend =c_int(1099)
cbeg =c_int(5500)
cend =c_int(6499)
ZLayer =c_int(0)
nBpp=24
nch = nBpp/8
roiW = 6499-5500+1
roiH = 1099-100+1
In MATLAB an array and pointer are defined:
img = uint8(zeros([roiW,roiH,nch]));
ptr = libpointer('uint8Ptr',img);
In PYTHON I think this is how it should be done for the Matlab equivalent, but this does not work and kills Python:
img = numpy.zeros([roiW,roiH,nch],dtype=ctypes.c_int8)
ptr=img.ctypes.data_as(ctypes.POINTER(ctypes.c_int8))
[status, fname, fpath, img]=GetImage(name,ID,strLibPath,Lvl,rbeg,rend,cbeg,cend,ZLayer, ptr)
How do I correctly create an array and pointer than can be fed to my DLL?
1 Answer 1
Manually creating all the c_int and c_char_p instances is unnecessary. But set the function pointer's argtypes to enable type checking.
The ctypes._as_parameter_ attribute of NumPy arrays is a c_void_p. If you prefer more strict type safety, use POINTER(c_uint8) in argtypes and data_as.
from ctypes import *
import numpy as np
__all__ = ['GetImage']
# WinDLL is stdcall; use CDLL for cdecl.
Wlib = WinDLL(r'C:\...\Wsl.dll')
Wlib.GetImage.argtypes = ([c_char_p, c_int, c_char_p] +
[c_int] * 6 +
[c_void_p])
def GetImage(name, ID, strLibPath, Lvl=0,
rbeg=100, rend=1099,
cbeg=5500, cend=6499,
ZLayer=0, nBpp=24):
roiW = cend - cbeg + 1
roiH = rend - rbeg + 1
nch = nBpp // 8
img = np.zeros([roiW, roiH, nch], dtype=np.uint8)
ImgBuffer = img.ctypes
status = Wlib.GetImage(name, ID, strLibPath, Lvl,
rbeg, rend, cbeg, cend,
ZLayer, ImgBuffer)
# test status
return img
I use from ctypes import * for convenience. You can import the wrapped C API into another module to get a clean namespace. It's common in Python to have one or more support modules and platform modules named with an initial underscore.
6 Comments
Wlib.GetImage(), Python dies without any errors, the Windows stopped working error comes up, and I can't make any sense from the Windows text error log. Is there a better way to test my DLL function and connection?img = np.zeros([roiH, roiW, nch], dtype=np.uint8). I missed that earlier. MATLAB uses Fortran-style column-major arrays, but NumPy defaults to C-style row-major arrays.int ID , const char * strLibPath are not supposed to be in the GetImage function. Now the program does not crash, but I get an access violation reading 0x0000000000000064 error that I am going to work on now. Thanks for your help, it pointed me in the right direction!0x0000000000000064 is the value for rbeg on the call stack. It looks like it's expecting a pointer for the argument index of strLibPath. Assuming you've eliminated ID and strLibPath from the call, change rbeg to 108 and see if the access violation changes with it to address 0x6c. If so the documentation is either correct or completely unreliable. ;)
[status, fname, fpath, img]?[status, fname, fpath, img] = calllib('WholeImg','GetImage', name, ID, strLibPath, Lvl, rbeg, rend,cbeg,cend,Zlayer,ptr)