将外部提供的缓冲区复制到字节

时间:2017-05-05 17:08:12

标签: python python-2.7 python-3.x ctypes

我使用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对象,然后再到bytes对象。

如何只使用一份副本?

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

1 个答案:

答案 0 :(得分:6)

显然你可以切片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))。