将外部提供的缓冲区复制到字节的最有效方法是什么
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]))
其中 buf
是 c_void_p
,len
是 c_int
。
据我了解,这执行了两个副本。一次到 bytearray 对象,然后再到 bytes 对象。
我怎样才能只用一个副本来做到这一点?
我目前的工作集中在 Python 2,但在适当的时候我也需要为 Python 3 提供支持。
显然你可以对 ctypes 指针进行切片。不是 c_void_p
、c_char_p
或 c_wchar_p
,但 POINTER
类型有效。对于 POINTER(c_char)
,将其切片得到 bytes
:
data = ctypes.POINTER(ctypes.c_char).from_buffer(buf)[:len.value]
感谢 eryksun 提出这个问题。此外,还不清楚为什么 buf
是 c_void_p
而不是已经是 POINTER(c_char)
。 (对于 POINTER(c_char)
,代码将只是 buf[:len.value]
。)
为了从支持缓冲协议的通用对象中获取bytes
,memoryview(...).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)
)。
我正在使用 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]))
其中 buf
是 c_void_p
,len
是 c_int
。
据我了解,这执行了两个副本。一次到 bytearray 对象,然后再到 bytes 对象。
我怎样才能只用一个副本来做到这一点?
我目前的工作集中在 Python 2,但在适当的时候我也需要为 Python 3 提供支持。
显然你可以对 ctypes 指针进行切片。不是 c_void_p
、c_char_p
或 c_wchar_p
,但 POINTER
类型有效。对于 POINTER(c_char)
,将其切片得到 bytes
:
data = ctypes.POINTER(ctypes.c_char).from_buffer(buf)[:len.value]
感谢 eryksun 提出这个问题。此外,还不清楚为什么 buf
是 c_void_p
而不是已经是 POINTER(c_char)
。 (对于 POINTER(c_char)
,代码将只是 buf[:len.value]
。)
为了从支持缓冲协议的通用对象中获取bytes
,memoryview(...).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)
)。