将解包代码从 perl 转换为 python
Converting unpack code from perl to 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))
都给 header[16]
0,正确的值应该是 9
要解压的文件在这里:
https://github.com/mishari/PMConverter/blob/main/src/tests/data/_PFC._PS
header的描述如下:
# 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 S
L15 S2
L L L L L L L L L L L L L L L S S
根据 documentation and my chart,
L
:本机字节顺序的 32 位无符号整数。
S
:本机字节顺序的 16 位无符号整数。
等价Python代码
struct.unpack
提供类似的功能。
L
和 =
:32 位无符号整数,采用本机字节顺序。
H
和 =
:16 位无符号整数,采用本机字节顺序。
对于 struct.unpack
,=
与整个格式字符串相关联,而不是与单个说明符相关联。另外,在信之前需要重复帐户。
所以,
my @header = unpack "L15 S2", $raw;
等同于
header = struct.unpack('= 15L 2H', raw)
正在解析 C 结构的二进制转储
但您并不是要复制 Perl 代码;而是要复制 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 在 Perl 中处理本机类型时比 unpack
更好的选择。 (确保使用 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("%zu\n", 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("%zu\n", 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.
中处理带有尾部填充的结构的简单方法
我正在尝试将以下解压缩代码转换为 Python:
my @header = unpack "L2L13SS", $raw;
我试过 struct.unpack("<L2L13HH", open(pfc_path,'rb').read(length))
和 struct.unpack("<L2L13BB", open(pfc_path,'rb').read(length))
都给 header[16]
0,正确的值应该是 9
要解压的文件在这里: https://github.com/mishari/PMConverter/blob/main/src/tests/data/_PFC._PS
header的描述如下:
# 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 S
L15 S2
L L L L L L L L L L L L L L L S S
根据 documentation and my chart,
L
:本机字节顺序的 32 位无符号整数。S
:本机字节顺序的 16 位无符号整数。
等价Python代码
struct.unpack
提供类似的功能。
L
和=
:32 位无符号整数,采用本机字节顺序。H
和=
:16 位无符号整数,采用本机字节顺序。
对于 struct.unpack
,=
与整个格式字符串相关联,而不是与单个说明符相关联。另外,在信之前需要重复帐户。
所以,
my @header = unpack "L15 S2", $raw;
等同于
header = struct.unpack('= 15L 2H', raw)
正在解析 C 结构的二进制转储
但您并不是要复制 Perl 代码;而是要复制 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 在 Perl 中处理本机类型时比 unpack
更好的选择。 (确保使用 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("%zu\n", 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("%zu\n", 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.
中处理带有尾部填充的结构的简单方法