Pointers and arrays in Python ctypes

68,866

Solution 1

You can cast with the cast function :)

>>> import ctypes
>>> x = (ctypes.c_ulong*5)()
>>> x
<__main__.c_ulong_Array_5 object at 0x00C2DB20>
>>> ctypes.cast(x, ctypes.POINTER(ctypes.c_ulong))
<__main__.LP_c_ulong object at 0x0119FD00>
>>> 

Solution 2

You can cast the result, but ctypes allows you to use an array in place of a pointer, directly. The issue is the byref in your code (which would be the equivalent of a pointer to a pointer):

So instead of:

cresult = (c_ulong * num)()
err = self.c_read_block(addr, byref(cresult), num)

try:

cresult = (c_ulong * num)()
err = self.c_read_block(addr, cresult, num)
Share:
68,866

Related videos on Youtube

Andrew Bainbridge
Author by

Andrew Bainbridge

Updated on August 31, 2020

Comments

  • Andrew Bainbridge
    Andrew Bainbridge over 3 years

    I have a DLL containing a C function with a prototype like this:

    int c_read_block(uint32 addr, uint32 *buf, uint32 num);

    I want to call it from Python using ctypes. The function expects a pointer to a chunk of memory, into which it will write the results. I don't know how to construct and pass such a chunk of memory. The ctypes documentation isn't much help.

    Constructing an array and passing it "byref", like this:

        cresult = (c_ulong * num)()
        err = self.c_read_block(addr, byref(cresult), num)
    

    Gives this error message:

    ArgumentError: argument 3: <type 'exceptions.TypeError'>: expected LP_c_ulong instance instead of pointer to c_ulong_Array_2

    I guess that is because the Python ulong array is nothing like a c uint32 array. Should I use create_char_string. If so, how do I persuade Python to "cast" that buffer to an LP_c_ulong?

  • Ralph Sinsuat
    Ralph Sinsuat over 14 years
    I've used ctypes a few times and I've encountered it in the linked documentation before.
  • Mike Vella
    Mike Vella almost 9 years
    Why i it a LP_c_ulong object and not LP_c_ulong_Array_5 object
  • Charles Grunwald
    Charles Grunwald over 7 years
    LP_c_ulong_Array_5 would be an address pointing to an address pointing to the first element in an array of uint32s, whereas the OP's function is looking to receive an address pointing to the first element of an array. LP_c_ulong_Array_5 would be for a function like: int c_read_block(uint32 addr, uint32 *buf[], uint32 num);