将 ctype 字节数组转换为字节

Posted

技术标签:

【中文标题】将 ctype 字节数组转换为字节【英文标题】:Convert ctype byte array to bytes 【发布时间】: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”的? 【参考方案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)

以上是关于将 ctype 字节数组转换为字节的主要内容,如果未能解决你的问题,请参考以下文章

Java将字节数组转换为十六进制字节数组[重复]

将字节数组转换为字符串并返回字节数组的问题

Java:将字节列表转换为字节数组

将 3 维字节数组转换为单字节数组 [关闭]

将字符串数组转换为字节数组

如何将字节数组的字符串转换为字节数组