如何将 c_uint 的 ctypes 数组转换为 numpy 数组

How to convert a ctypes array of c_uint to a numpy array

我有以下 ctypes 数组:

data = (ctypes.c_uint * 100)()

我想创建一个 numpy 数组 np_data 包含来自 ctypes 数组数据的整数值(ctypes 数组显然稍后会填充值)

我已经看到 numpy 中有一个 ctypes 接口 (https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.ctypes.html),但据我所知,这只是从 numpy 数组中获取 ctypes 而不是相反的。

我显然可以遍历 data 并逐个填充 np_data 数组项,但我想知道是否有更多 efficient/straightforward 方法来完成此任务。

你可以使用 [NumPy]: numpy.ctypeslib.as_array(obj, shape=None).

>>> import ctypes as ct
>>> import numpy as np
>>>
>>>
>>> CUIntArr10 = ctypes.c_uint * 10
>>>
>>> ui10 = CUIntArr10(*range(10, 0, -1))
>>>
>>> [e for e in ui10]  # The ctypes array
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>>
>>> np_arr = np.ctypeslib.as_array(ui10)
>>> np_arr  # And the np one
array([10,  9,  8,  7,  6,  5,  4,  3,  2,  1], dtype=uint32)

没有到达特定的代码行(我也没有测试我的假设),但我感觉内容复制是通过单个 memcpy 调用完成的,这将比 Python.

中“手动”执行操作快得多

可能最快的是使用 np.frombuffer。它可以与实现缓冲区协议的每个对象一起使用,特别是与 ctypes 数组一起使用。

np.frombuffer 的主要优点是,ctypes 数组的内存根本不被复制,而是共享:

data = (ctypes.c_uint * 100)()
arr = np.frombuffer(data, dtype=np.uint32)
arr.flags
# ...
# OWNDATA : False
# ...

通过设置

arr.flags.writable = False

可以确保不会通过 numpy 数组更改数据 arr

如果确实需要复制数据,通常的 numpy 功能可以用于 arr


中提出的 np.ctypeslib.as_array 似乎是创建 numpy 数组的更好方法:

  • 内存也是共享的——不涉及复制。
  • 右边的 dtype 自动使用(这是一件好事:它消除了错误(就像在我原来的 post 中一样,我在其中使用了 np.uint (意味着 64 位无符号我机器上的整数)而不是 np.uint32(这在某些架构上也可能不正确)。

以上实验证明:

arr = np.ctypeslib.as_array(data)
arr.flags
# ...
# OWNDATA : False
# ...
arr.dtype
# dtype('<u4')