Python 可写缓冲区/内存视图到数组/字节数组/ctypes 字符串缓冲区

Posted

技术标签:

【中文标题】Python 可写缓冲区/内存视图到数组/字节数组/ctypes 字符串缓冲区【英文标题】:Python writable buffer/memoryview to array/bytearray/ctypes string buffer 【发布时间】:2013-09-24 13:28:41 【问题描述】:

问题:

固定大小记录的二进制数据 想使用 struct.unpack_from 和 struct.pack_into 来操作二进制数据 不想要数据的副本 希望多个视图进入内存以简单地偏移计算等。 数据可以在 array.array bytearray 或 ctypes 字符串缓冲区中

我想做什么:

part1 = buffer(binary_data, 0, size1)
part2 = buffer(binary_data, size1, size2)
part3 = buffer(binary_data, size1 + size2) # no size is given for this one as it should consume the rest of the buffer
struct.pack_into('I', part3, 4, 42)

这里的问题是 struct.pack_into 抱怨缓冲区是只读的。我研究了内存视图,因为它们可以创建读/写视图,但是它们不允许您像缓冲区函数那样指定偏移量和大小。

如何实现将多个零拷贝视图放入一个可读、可写并且可以使用 struct.unpack_from 和 struct.pack_into 访问/修改的字节缓冲区

【问题讨论】:

我可以做到,但我希望有更好的方法。我希望能够创建几个具有固定大小和偏移量的缓冲区。这样,pack_into 调用就不必计算总偏移量,只需计算我正在写入的特定结构/片段的偏移量。如果我直接打包到结构中,我的所有调用将看起来像 pack_into(fmt, buffer, part_offset + offset, v1, v2 ...) 而不是 pack_into(fmt, buffer, offset, v1, v2, ...) 我真的试图避免每次都计算数据的总偏移量。 【参考方案1】:

在 2.6+ 中,ctypes 数据类型有一个 from_buffer 方法,它采用可选的偏移量。它需要一个可写缓冲区,否则会引发异常。 (对于只读缓冲区,有 from_buffer_copy。)这是您使用 ctypes char 数组的示例的快速翻译:

from ctypes import *
import struct

binary_data = bytearray(24)
size1 = size2 = 4
size3 = len(binary_data) - size1 - size2

part1 = (c_char * size1).from_buffer(binary_data)
part2 = (c_char * size2).from_buffer(binary_data, size1)
part3 = (c_char * size3).from_buffer(binary_data, size1 + size2)
struct.pack_into('4I', part3, 0, 1, 2, 3, 4)

>>> binary_data[8:]
bytearray(b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00')

>>> struct.unpack_from('4I', part3)
(1, 2, 3, 4)

【讨论】:

这被标记为 2.7,所以我没有提到memoryview。在 3.x 中,memoryview 对象与 struct.pack_into 一起使用。使用切片创建新视图的能力比这种 ctypes 方法更方便。

以上是关于Python 可写缓冲区/内存视图到数组/字节数组/ctypes 字符串缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

ByteArrayOutputStream 类源码分析

字节数组流ByteArrayInputStream&ByteArrayOutputStream

Java 流(Stream)文件(File)和IO -- Java ByteArrayOutputStream类

编写一个C语言的内存拷贝函数,把源地址的指定长度的数据拷贝到目标地址,考虑8,16,32位数据位宽

将可写 StringBuilder 数组从 C# 传递给 C++

将字节数组转换为标准数据类型