Python ctypes中的指针和数组

45 投票
3 回答
81861 浏览
提问于 2025-04-15 14:00

我有一个DLL文件,里面有一个C语言的函数,函数的原型是这样的:

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

我想用Python通过ctypes来调用这个函数。这个函数需要一个指向内存块的指针,结果会写到这个内存块里。但是我不知道怎么构造并传递这样一个内存块。ctypes的文档对我帮助不大。

我尝试构造一个数组并通过“引用”传递,像这样:

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

结果出现了这个错误信息:

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

我猜这是因为Python的ulong数组和C语言的uint32数组完全不一样。我应该使用create_char_string吗?如果是的话,我该怎么让Python把这个缓冲区“转换”成LP_c_ulong呢?

3 个回答

-2

这个解决方案里有个拼写错误。要获取一个指向无符号长整型数组的指针,你需要把它转换成一个 POINTER(list of ulong)

In [33]: ptr = ctypes.cast(x, ctypes.POINTER(ctypes.c_ulong*5))
In [34]: ptr
Out[34]: <__main__.LP_c_ulong_Array_5 at 0x23e2560>
4

你可以把结果转换成其他类型,但ctypes让你可以直接用数组代替指针。问题在于你代码里的byref(这相当于指向指针的指针):

所以不要这样写:

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

试试这样:

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

你可以使用 cast 这个函数来进行类型转换哦 :)

>>> 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>
>>> 

撰写回答