【问题标题】:Convert ctype byte array to bytes将 ctype 字节数组转换为字节
【发布时间】:2013-03-13 04:53:10
【问题描述】:

我有一个这样定义的 ctypes 数组:

buff= (c_ubyte*buff_size)()

用数据填充缓冲区后,我需要以字节格式保存这些数据。现在我这样做如下:

buff= [n for n in buff]
buff = ''.join(map(chr, buff))

这样做的问题是它在将其转换回单字节字符串之前将其转换为 4 字节(或任何字节数)的 int,这会浪费大量 CPU。

如何将 ctypes 缓冲区直接转换为字节?我不想为自己保存一份副本,因为无论如何我都必须做一份副本,因为我无法保留原始缓冲区。 python 对这些东西有强制转换功能吗?

谢谢。

【问题讨论】:

  • 你最初是如何将数据输入“buff”的?

标签: python-2.7 ctypes


【解决方案1】:

如果您确实想要一份副本,您可以使用bytearray

>>> buff = (c_ubyte * 4)(*[97,98,99,100])
>>> bs = bytearray(buff)
>>> bs
bytearray(b'abcd')
>>> str(bs)
'abcd'

编辑

对于 2.6 之前的 Python 版本缺少 bytearray,您可以 请改用以下方法之一:

  • cast(buff, c_char_p).value
  • buffer(buff)[:]

如果你想共享同一个缓冲区,你可以创建一个c_char数组:

>>> buff2 = (c_char * len(buff)).from_buffer(buff)
>>> buff2.value # string copy
'abcd'
>>> buff2[:] = 'efgh'
>>> buff[:]  # modified original
[101, 102, 103, 104]

编辑

from_buffer 类方法是在 2.6 中添加的。在以前的版本中,您 可以使用cast:

  • buff2 = cast(buff, POINTER(c_char * len(buff)))[0]

您不使用c_char 数组是否有原因?我了解您是否需要将其作为数字数组和字符串来使用。

附录:

第二种方法更像是“强制转换”,因为它不复制缓冲区。第一种方法会被复制两次,一次是创建bytearray,另一次是创建strbytesstr 在2.x 中的别名)。但是 bytearray 有字符串方法,可能就是你所需要的;它基本上是 3.x bytes 的可变版本。

c_char 是 C char 类型。乘以一个数组,它是一个可变的字节缓冲区,就像您当前的 c_ubyte 数组一样。但是,它可能比 c_ubyte 更方便,因为它具有返回 Python 字节字符串的 valueraw 描述符。它还将索引和迭代作为单个字符字节字符串而不是整数。

如果函数将修改它,你不应该做的是从 Python 字符串创建一个 c_char_p - 一个指向字符数据的指针。 Python 字符串对象是不可变的;如果你修改他们的缓冲区,你会得到奇怪的错误。我最近在那个话题上answered a question

【讨论】:

  • 第一个解决方案有效,但我不得不使用字节(bytearray(buff)),因为没有一个单独工作。我不使用 c_char 的原因;对于一个我仍然需要转换为字节,其次,我认为 c_char 应该是不可变的,所以我将无法修改我的 dll 中的缓冲区。尽管从 ctypes 文档中我不清楚这里认为什么是可变的。
  • 哪里提到 bytes() 和 bytearray() 复制对象?因为我仍然在使用第二种方法时遇到问题。使用 '((ctypes.c_char * len(buff)).from_buffer(buff)).raw' 我得到 '"TypeError: expected a writeable buffer object"' 并使用 '.value' 来切断缓冲区,可能在第一个 \00。
  • 我必须做 from_buffer_copy,否则它会崩溃。谢谢!
  • value 将在 null 处切断。当库将空终止字符串写入缓冲区时,它很有用。 buff 是如何创建为只读的?如果它不是缓冲区(例如(c_char * 4).from_buffer([1,2,3,4]))或缓冲区是只读的或无法说明它有多少段(应该只有 1 个段),则 PyObject_AsWriteBuffer 会引发该异常。
  • @michael,仅供参考,memoryview 替换 PY3 中的 buffer,因此等效转换为 memoryview(buff).tobytes(),但更简单地说,它只是 bytes(buff)
猜你喜欢
  • 1970-01-01
  • 2019-11-24
  • 2014-08-08
  • 1970-01-01
  • 2021-11-11
  • 2011-07-02
  • 2019-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多