将解压代码从perl转换为python
我正在尝试将以下解包代码转换为 Python:
my @header = unpack "L2L13SS", $raw;
我试着struct.unpack("<L2L13HH", open(pfc_path,'rb').read(length))和struct.unpack("<L2L13BB", open(pfc_path,'rb').read(length))均可以得到0 header[16],正确的值应该是9
要解压的文件在这里:https :
//github.com/mishari/PMConverter/blob/main/src/tests/data/_PFC._PS
标题已按以下方式描述:
# The pfc file seems to start with the following header
# struct PfcHead
# {
# long id1; // Seems to contain 0x005344f4
# long id2; // Seems to contain 0x01234567
# long rsvd[13]; // Zeros
# short s1; // Seems like number of fields minus one?
# short s2; // Number of field structures
# };
回答
理解 Perl 代码
L2L13SS 也可以写成
L L L13 S SL15 S2L L L L L L L L L L L L L L L S S
根据文档和我的图表,
L:本机字节顺序的 32 位无符号整数。S:本机字节顺序的 16 位无符号整数。
等效的 Python 代码
struct.unpack 提供类似的功能。
Lwith=:本机字节顺序的 32 位无符号整数。Hwith=:本机字节顺序的 16 位无符号整数。
与struct.unpack,=与整个格式字符串而不是单个说明符相关联。此外,在信件之前预计会有重复帐户。
所以,
my @header = unpack "L15 S2", $raw;
相当于
header = struct.unpack('= 15L 2H', raw)
解析 C 结构的二进制转储
但是您并不是要复制 Perl 代码;您正在尝试读取该 C 结构。
正在使用的 Perl 模式 ( L15 S2) 不等同于您发布的 C 结构。
long是有符号类型。long可能长于 32 位。short是签名类型。short可能长于 16 位。- C 编译器可以自由地在字段之间放置填充,尽管没有编译器会为这种结构。
- C 编译器可以自由地在末尾放置填充。这在具有 16 位短和 64 位长的编译器上是可能的。这其实很常见。
l!15 s!2 会更接近正确的模式。
l!:long本机字节顺序的本机。s!:short本机字节顺序的本机。
但这假设没有填充,这是一个问题。这就是为什么Convert::Binary::C比unpack在 Perl 中处理本机类型更好的选择。(请务必使用Alignment => 0。)
在 Python 中,您可以使用以下内容更准确地表示 C 结构:
header = struct.unpack('@ 15l 2h', raw)
要不就
header = struct.unpack('15l 2h', raw)
使用@(或根本没有符号),struct.pack将在适当的地方添加字段间填充。
$ cat a.c
#include <stdio.h>
struct Foo {
char c;
short s;
};
int main(void) {
printf("%zun", sizeof(struct Foo));
}
$ gcc -Wall -Wextra -pedantic a.c -o a && ./a
4
$ python3 -c 'import struct; print(len(struct.pack("bh", 0, 0)))'
4
但是,它不会在应该添加尾随填充。
$ cat a.c
#include <stdio.h>
struct PfcHead {
long id1;
long id2;
long rsvd[13];
short s1;
short s2;
};
int main(void) {
printf("%zun", sizeof(struct PfcHead));
}
$ gcc -Wall -Wextra -pedantic a.c -o a && ./a
128
$ python3 -c 'import struct; print(len(struct.pack("15l 2h", *((0,)*17))))'
124
我不知道在 Python 中处理带有尾随填充的结构的简单方法。