将外部提供的缓冲区复制到字节的最有效方法是什么

What is the most efficient way to copy an externally provided buffer to bytes

我正在使用 ctypes 连接到外部库。这个库 returns 对我来说是一个二进制缓冲区。界面如下所示:

int getBuff(unsigned char **buf, int *len);

该库还导出了一个释放器,这样我就可以在使用完后释放缓冲区,但是这方面对我来说没有问题,所以我认为我们不需要覆盖它。

在我的 ctypes 代码中,我将 buf 参数表示为 c_void_p。我想尽可能高效地将此缓冲区复制到字节对象中。

目前我有:

data = bytes(bytearray(ctypes.cast(buf, ctypes.POINTER(ctypes.c_ubyte*len.value))[0]))

其中 bufc_void_plenc_int

据我了解,这执行了两个副本。一次到 bytearray 对象,然后再到 bytes 对象。

我怎样才能只用一个副本来做到这一点?

我目前的工作集中在 Python 2,但在适当的时候我也需要为 Python 3 提供支持。

显然你可以对 ctypes 指针进行切片。不是 c_void_pc_char_pc_wchar_p,但 POINTER 类型有效。对于 POINTER(c_char),将其切片得到 bytes:

data = ctypes.POINTER(ctypes.c_char).from_buffer(buf)[:len.value]

感谢 eryksun 提出这个问题。此外,还不清楚为什么 bufc_void_p 而不是已经是 POINTER(c_char)。 (对于 POINTER(c_char),代码将只是 buf[:len.value]。)


为了从支持缓冲协议的通用对象中获取bytesmemoryview(...).tobytes()bytes(bytearray(...))少了一个副本:

data = memoryview(ctypes.cast(buf, ctypes.POINTER(ctypes.c_ubyte*len.value))[0]).tobytes()

这与 Python 2 和 Python 3 兼容。


记住这里的buf需要是指向缓冲区的指针,而不是指向缓冲区的指针。 getBuff 接受一个指向指针的指针(所以可能 byref(buf))。