I'm new to ctypes, and I'm currently working on a project that must pass a 2d array using pointer into a dll using ctypes. But since the dll file has been locked, I'm unable to view and edit the c library file but can only guess that I must pass an pointer to a pointer of c_ubytes into the function I'm calling.
I think I'm having trouble with correctly using ctypes but I tried different methods(described below) I found here on stackoverflow, and they kept giving different errors, but mostly OSError: exception: access violation reading 0x00000267045A72B0
I want to ask that if there's any other way that I can try to solve this problem? Or is this dll problem (which I can't solve :'( ) Thanks!
The original code is as follows:
#includes the dll file
path=os.path.abspath(os.path.dirname(__file__))
winDLL = ct.CDLL(path+'/dlls/slm_win_ctrl.dll')
...
#function is called here
def update(array):
Arr = ndarray2carray(array,"b")
winDLL.window_show(pArr) #<----
return
where the ndarray2carray function converts the nd array passed into the function to a ctype array:
def ndarray2carray(ndarr,type):
arr_flat = list(ndarr.reshape(-1))
if type == 'd':
arr_c = (ct.c_double*len(arr_flat))(*arr_flat)
elif type == 'b':
arr_c = (ct.c_ubyte*len(arr_flat))(*arr_flat)
elif type == 'i':
arr_c = (ct.c_int*len(arr_flat))(*arr_flat)
elif type == 'f':
arr_c = (ct.c_float*len(arr_flat))(*arr_flat)
else:
print("type_undefine!")
print("enter 'b' for byte,'d' for double,'i' for int.")
return
return arr_c
but the terminal shows the following error code:
OSError: exception: access violation reading 0x00000267045A72B0
I tried to print out the Arr object and ct.pointer(array), but found out that the address it shows is different.
Array: <slm_lib.slm_CGH.c_ubyte_Array_2073600 object at 0x000002B18A2FFE40> Array pointer: <slm_lib.slm_CGH.LP_c_ubyte_Array_2073600 object at 0x000002B18A3950C0>
First I found that I haven't declared argtypes of the function, so I modify the code into:
def update(array):
Arr = ndarray2carray(array,"b")
pArr = ct.pointer(Arr)
winDLL.window_show.argtypes = [type(pArr)]
winDLL.window_show.restype = None
winDLL.window_show(pArr)
return
but this gives: OSError: exception: access violation reading 0x00000267045A72B0
Then I tried to directly set argtype as pointer to a pointer:
def update(array):
Arr = ndarray2carray(array,"b")
winDLL.window_show.argtypes = [ct.POINTER(ct.POINTER(ct.c_ubyte))]
winDLL.window_show.restype = None
winDLL.window_show(ct.pointer(Arr))
return
but this gives: ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_LP_c_ubyte instance instead of LP_c_ubyte_Array_2073600
Since their type doesn't match, I tried this:
def update(array):
Arr = ndarray2carray(array,"b")
pArr = ct.pointer(Arr)
winDLL.window_show.argtypes = [type(pArr)]
winDLL.window_show.restype = None
print("Array:",Arr)
print("Array pointer",pArr)
winDLL.window_show(pArr)
return
but I get (from the print function and the error) Array: <slm_lib.slm_CGH.c_ubyte_Array_2073600 object at 0x0000021632A3BAC0> Array pointer <slm_lib.slm_CGH.LP_c_ubyte_Array_2073600 object at 0x0000021632AD8FC0> ... OSError: exception: access violation reading 0x0000021665AB22B0
finally I tried this solution I found on stackoverflow but it gives the same error as above.
def update(array):
#ubyte pointers
uPtr = ct.POINTER(ct.c_ubyte)
uPtrPtr = ct.POINTER(uPtr)
#initialize dll function
winDLL.window_show.argtypes = [uPtrPtr]
winDLL.window_show.restypes = ct.c_ubyte
#convert np array into c array
print(array)
ct_arr = np.ctypeslib.as_ctypes(array)
ptr_arr = uPtr * ct_arr._length_
ct_ptr = ct.cast(ptr_arr(*(ct.cast(row, uPtr) for row in ct_arr)), uPtrPtr)
#pass into the function
winDLL.window_show(ct_ptr)
return