2

我有一组数据代表我需要在 python 中操作的硬件结构。真正的结构大小为 4 KB……我将举一个简单的例子:

Byte(s)  Value  
0-1      0x0102
2-3      0x0304
4-23     "AStrWith20Characters"
24-63    "WoahThisStringHas40CharactersItIsHuge!!!"
64-71    "Only8Chr"
72-74    0x050607
74       0x08
75-127   0x00 (padding)

我的想法是我将这个结构打包成一个 32 位 Int 列表,将列表传递给另一个函数,然后函数将整个 shebang 写入内存。内存写入函数一次接受 64 个字节,所以我必须进行两次调用。

因此,对于上面的示例,我需要进行这些调用(为了便于阅读,我将使用大端序):

WrToMemory([0x01020304, 0x41537472, 0x57697468, 0x3230436, 
            0x61726163, 0x74657273, 0x576F6168, 0x5468697, 
            0x53747269, 0x6E674861, 0x73343043, 0x6861726, 
            0x63746572, 0x73497449, 0x73487567, 0x65212121])

WrToMemory([0x4F6E6C79, 0x38436872, 0x05060708, 0x00000000,  
            0x00000000, 0x00000000, 0x00000000, 0x00000000,  
            0x00000000, 0x00000000, 0x00000000, 0x00000000,  
            0x00000000, 0x00000000, 0x00000000, 0x00000000])    

问题是我不知道如何以任何有效的方式打包这些数据。我一直在努力使用structand array,但要么我在概念上遗漏了一些东西,要么我只是使用了错误的工具来完成这项工作。

最终,我知道我可以编写一个毛茸茸的大函数来检查数据类型,执行一系列移位和屏蔽,将 ASCII 转换为十六进制,以及构造我需要的数据包。但这似乎……不优雅。

我认为必须有一种方法告诉 python“这是一个两个字节长的数字。打包它。另一个两个字节的数字,将它附加到最后一个。现在这是一个字符串,有 20 个字节。附加它. 继续直到我们有 64 字节。然后将我们刚刚制作的 64 字节列表转换为 16 个无符号整数的 lsit。

似乎packandunpack函数是我应该使用的,但就像我上面所说的......我一定遗漏了一些东西。例如,如何pack处理 3 字节数?如果您使用类似 的格式字符串HB,则pack需要两个参数:

>>> pack('HB', 0x050607)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: pack requires exactly 2 arguments

而且我不能使用unpack,因为它需要一个字符串,而不是数字。

希望我已经把我的问题说清楚了。任何帮助深表感谢!

4

2 回答 2

2

您使用的是正确的工具,但您告诉 pack 编码 2 个参数,但只传递一个。

字符串的HB意思是:打包两个值,一个为无符号短,另一个为无符号字节。传入两个值,它可以工作:

>>> pack('HB', 0x0506, 0x07)
'\x06\x05\x07'

只要不断尝试,你就会掌握它的窍门。以下是您示例中的第一组值,采用 Big Endian 表示法:

>>> pack('>2H20c40c', 0x0102, 0x0304)
'\x01\x02\x03\x04AStrWith20CharactersWoahThisStringHas40CharactersItIsHuge!!!'

注意开头的“>”,这表示字节序。字符串被转换为序列并作为单独的变量应用。通常,尽管附加它们更容易:

>>> pack('>2H20c40c', 0x0102, 0x0304) + "AStrWith20Characters" + "WoahThisStringHas40CharactersItIsHuge!!!"
'\x01\x02\x03\x04AStrWith20CharactersWoahThisStringHas40CharactersItIsHuge!!!'
于 2012-08-23T20:07:28.897 回答
0

您可以pack使用您的 struct 格式进行整个操作,并使用例如 32 位字格式对其进行解包:

>>> format="cchi"
>>> p=pack(format,"a","b",1,2)
>>> p
'ab\x01\x00\x02\x00\x00\x00'
>>> (z1,z2)=unpack("ii",p)
>>> (z1,z2)
(90721, 2)
于 2012-08-23T20:16:49.417 回答