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



我使用ctypes接口到外部库。这个库返回给我一个二进制缓冲区。界面看起来像这样:

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

图书馆还会导出一个deallocator,以便在完成时可以释放缓冲区,但是这方面对我没有任何问题,所以我认为我们不需要覆盖。

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

目前我有:

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

其中bufc_void_plenc_int

我理解,这执行了两个副本。一旦到达bytearray对象,然后再次到达字节对象。

我只能只用一个副本执行此操作?

我目前的努力集中在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)(。

最新更新