0

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
yihsin
  • 1

0 Answers0