I'm writing a wrapper for a C dll in Python Ctypes. In the C library I have a function of the kind
int32 Transfer ( ..., PIN_PARAMS_TRANSFERDATA pInData, ... )
where PIN_PARAMS_TRANSFERDATA is a pointer to this structure:
typedef struct
{
...
void * pDataBuffer; //!< Pointer to application-allocated buffer to hold requested data.
} IN_PARAMS_TRANSFERDATA, *PIN_PARAMS_TRANSFERDATA;
The data type of the DataBuffer depends can change, but is usually int16 in my case. In ctypes I defined the structure and the function as follows:
class IN_PARAMS_TRANSFERDATA(Structure):
_fields_ = [
...,
('pDataBuffer', c_void_p)
]
_lib = CDLL('mydll.dll')
_lib.Transfer.argtypes = [..., POINTER(IN_PARAMS_TRANSFERDATA), ...]
_lib.Transfer.restype = c_int32
def Transfer(system, in_data):
status = _lib.Transfer(..., byref(in_data), ...)
return in_data
Now I have the problem that I have to define a data buffer before calling the Transfer function, which I don't manage. I tried the following (the 2000 is just for testing and should rather be a variable):
in_data = IN_PARAMS_TRANSFERDATA()
data_buffer = (c_int16*2000)()
print(data_buffer)
in_data.pDataBuffer = byref(data_buffer)
in_data = Transfer(hsystem, in_data)
The output message is:
<__main__.c_short_Array_2000 object at 0x00000000053D2EC8>
Traceback (most recent call last):
File ".../test.py", line 48, in <module>
in_data.pDataBuffer = byref(data_buffer)
TypeError: cannot be converted to pointer
Can anybody help me, how to create the data buffer properly and pass it to the structure (and finally to the C function), such that the C function can write data into it and I can read the data out (e.g. as a numpy.array).
In case this helps, this is how the creation of the buffer pointer is done in an example C program (unfortunately I don't really understand what's going on):
void* pBuffer = NULL;
pBuffer = VirtualAlloc(NULL, (size_t)((i64TransferLength + i64Padding) * u32SampleSize), MEM_COMMIT, PAGE_READWRITE);
EDIT
Following J.F. Sebastian's suggestion, I changed the creation of the buffer slightly:
data_buffer = (c_int16*2000)()
p_data_buffer = ctypes.cast(data_buffer, POINTER(c_int16*2000))
in_data.pDataBuffer = p_data_buffer
which gives me a slightly different error now:
Traceback (most recent call last):
File ".../test.py", line 50, in <module>
in_data.pDataBuffer = p_data_buffer
TypeError: incompatible types, LP_c_short_Array_2000 instance instead of c_void_p instance
byref(data_buffer), tryctypes.cast(data_buffer, ctypes.POINTER(ArrayType))whereArrayType = c_int16*2000See Pointers and arrays in Python ctypes `in_data.pDataBuffer, because the type doesn't matchc_void_p. I'll update the question.cast(data_buffer, c_void_p)?list(in_data.pDataBuffer)to obtain a list with all the elements in the buffer. But I get the error, that'long' object is not iterable. I tried to cast back toPOINTER(c_int16*2000)and then applylist()but this runs forever without any result.