Python ctypes 中的指针和数组

Posted

技术标签:

【中文标题】Python ctypes 中的指针和数组【英文标题】:Pointers and arrays in Python ctypes 【发布时间】:2010-11-24 16:35:39 【问题描述】:

我有一个包含 C 函数的 DLL,其原型如下:

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

我想使用 ctypes 从 Python 调用它。该函数需要一个指向一块内存的指针,它将结果写入其中。我不知道如何构造和传递这么一大块内存。 ctypes 文档帮助不大。

构造一个数组并将其传递给“byref”,如下所示:

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?

【问题讨论】:

【参考方案1】:

您可以使用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>
>>> 

【讨论】:

我用过ctypes几次,之前在链接文档中遇到过。 为什么我是LP_c_ulong 对象而不是LP_c_ulong_Array_5 对象 LP_c_ulong_Array_5 将是一个地址,该地址指向一个指向uint32s 数组中第一个元素的地址,而 OP 的函数正在寻找一个指向第一个元素的地址大批。 LP_c_ulong_Array_5 将用于如下功能:int c_read_block(uint32 addr, uint32 *buf[], uint32 num);【参考方案2】:

您可以转换结果,但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)

【讨论】:

【参考方案3】:

解决方案中有错字。为了获得指向 ulongs 数组的指针,您需要强制转换为 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>

【讨论】:

以上是关于Python ctypes 中的指针和数组的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ctypes 将数组从 C++ 函数返回到 Python

ctypes给扩展模块中的函数传递数组和结构体

python ctypes:从指针变量中获取指向类型

python ctypes中的多维char数组(字符串数组)

[转] python关于ctypes使用char指针与bytes相互转换的问题

如何将指向c数组的指针转换为python数组