我有一个我这样定义的ctypes数组:
buff= (c_ubyte*buff_size)()
用数据填充缓冲区后,我需要以字节格式存储这些数据。现在我正按以下方式进行:
buff= [n for n in buff]
buff = ''.join(map(chr, buff))
这个问题是它将它转换为4字节(或任意数量的字节)int,然后再将其转换回单字节字符串,这会浪费大量的CPU。
如何直接将ctypes缓冲区转换为字节?我不是想保存自己的副本,因为我无论如何都要做副本,因为我无法保留原始缓冲区。 python是否有针对此类内容的强制转换功能?
感谢。
答案 0 :(得分:15)
如果您确实需要副本,可以使用bytearray
:
>>> buff = (c_ubyte * 4)(*[97,98,99,100])
>>> bs = bytearray(buff)
>>> bs
bytearray(b'abcd')
>>> str(bs)
'abcd'
修改强>:
对于缺少
bytearray
的2.6之前的Python版本,您可以 请改用以下其中一项:
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]
修改强>:
2.6中添加了
from_buffer
类方法。在以前的版本中你 可以使用cast
:
buff2 = cast(buff, POINTER(c_char * len(buff)))[0]
您是否有理由不使用c_char
数组开头?我理解你是否需要将它作为数值数组和字符串使用。
附录:
第二种方法更像是“强制转换”,因为它不会复制缓冲区。第一种方法是复制两次,一次复制bytearray
,再次复制str
(bytes
是2.x中str
的别名。但是bytearray
有字符串方法,可能就是你所需要的;它基本上是3.x bytes
的可变版本。
c_char
是C char
类型。乘以数组,它是一个可变的字节缓冲区,就像当前的c_ubyte
数组一样。但是,它可能比c_ubyte
更方便,因为它具有返回Python字节字符串的value
和raw
描述符。它还索引和迭代为单字符字节字符串而不是整数。
如果函数将修改它,那么你不应该做的是从Python字符串创建一个c_char_p
- 一个指向字符数据的指针。 Python字符串对象是不可变的;如果修改缓冲区,你可能会得到奇怪的错误。我最近answered a question就这个话题发了言。