14

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

buff= (c_ubyte*buff_size)()

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

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

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

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

谢谢。

4

1 回答 1

19

如果您确实想要一份副本,您可以使用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数组开始?我了解您是否需要将它作为数字数组和字符串来使用。

附录:

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

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

如果函数将修改它,您不应该做的是c_char_p从 Python 字符串创建一个 - 指向字符数据的指针。Python 字符串对象是不可变的;如果你修改他们的缓冲区,你会得到奇怪的错误。我最近回答了一个关于该主题的问题。

于 2013-03-13T10:12:31.707 回答