Python:如何使用struct.pack_into将不同类型的数据打包到字符串缓冲区中
我正在尝试把一些无符号整数数据放进一个用 ctypes.create_string_buffer
创建的字符串缓冲区里。
下面是相关的代码片段,还有一个运行示例,展示了错误的情况,链接在这里:codepad:
import struct
import ctypes
import binascii
buf = ctypes.create_string_buffer(16)
struct.pack_into("=I=I=I", buf, 0, 1, 2, 3)
print binascii.hexlify(buf)
这段代码会出现以下错误:
...
struct.error: bad char in struct format
文档里没有说明如果底层缓冲区是特定的C类型,是否可以把不同类型的数据放进去。在这个例子中,我试图把无符号整数数据放进一个底层类型为c_char的字符串缓冲区。有没有人知道怎么解决这个问题,或者有没有特定的方法可以创建一个可以放任何类型数据的缓冲区?
3 个回答
1
标准操作流程:先看看错误信息。
“bad char in struct format”就是字面意思。
标准操作流程:查阅文档。这里提到“格式字符串的第一个字符可以用来表示打包数据的字节顺序、大小和对齐方式”,并且列出了=
作为一种可能性。接下来的部分(格式字符)列出了很多字母,其中包括I
。
结论:你的格式字符串应该是"=III"
。
注意:这个问题和目标缓冲区完全没有关系,更不用说它底层的C类型了:
>>> import struct
>>> struct.pack("=I=I=I", 1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: bad char in struct format
>>> struct.pack("=III", 1, 2, 3)
'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
>>>
4
抱歉打扰老话题,但我明白“snap”的意思了——可能是因为我有类似的背景习惯。
“格式字符串的第一个字符可以用来表示打包数据的字节顺序、大小和对齐方式。”我同意这个说法。不过:
- Python的文档故意(?)没有给出任何关于顺序格式化的使用示例(所有示例都假设使用本机字节顺序、大小和对齐方式,且是在大端机器上。)
- 人们可能会假设(就像我和可能的snap一样),"
III
"由三个格式字符串组成,我们可以随意格式化每一个。因此=I=I=I
。我在习惯了Ruby的array.pack后,自己给自己挖了个坑,因为在Ruby中可以在表达式中自由改变顺序(在这种情况下,Ruby的等价写法是I_I_I_
,因为顺序选择符在类型之后)。
所以我觉得在struct.pack/unpack的文档中加几行,给出顺序和填充的使用示例可能会很好(唉,填充对我打击更大……我本可以适应本机顺序,但填充毁了我的协议)。
12
你不需要在每个输出的说明前面都加上'='这个代码。只需要说一次就可以了:
struct.pack_into("=III", buf, 0, 1, 2, 3)
这样就会得到:
01000000020000000300000000000000