【问题标题】:What is the most efficient way to copy an externally provided buffer to bytes将外部提供的缓冲区复制到字节的最有效方法是什么
【发布时间】:2017-10-04 06:12:45
【问题描述】:

我正在使用 ctypes 连接到外部库。这个库返回给我一个二进制缓冲区。界面如下所示:

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 提供支持。

【问题讨论】:

  • 在 Python 3 上,您应该可以只删除 bytearray 调用。
  • 你为什么要使用带有演员表的c_void_p 而不仅仅是buf = POINTER(c_char)?然后getBuff(byref(buf), byref(len))data = buf[:len.value]
  • @eryksun:嗯。您可以切片 ctypes 指针吗?给我的消息。
  • @user2357112,它必须是_Pointer instance。简单指针类型(c_void_pc_char_pc_wchar_p)是_SimpleCData 的子类,并且只有value。但我发现我的第一条评论中有错字。我错过了将其实例化为 buf = POINTER(c_char)() 的调用。
  • @eryksun 为什么?因为我不知道更好。一如既往地感谢您的知识贡献。

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


【解决方案1】:

显然您可以对 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))。

【讨论】:

  • 谢谢。是的,双指针是为了让库可以将指针返回给调用者。但在我的 ctypes 代码中,buf 是指向缓冲区的指针。
  • @eryksun:我看了看,哇,cast 实际上是一个 FFI 调用,而不是常规的内置函数或 Python 函数,而且它实际上非常慢。在环境中每次调用超过一微秒,我仅在 cast 调用中对其进行了测试,而指针切片大约需要 67 纳秒,memoryview(x).tobytes() 大约需要 285 纳秒(使用 10 元素测试数组)。跨度>
  • @eryksun:你的意思是ctypes.POINTER(ctypes.c_char),还是有一些API 奇怪,意味着我们实际上应该使用ctypes.POINTER(ctypes.c_char_p)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
相关资源
最近更新 更多