将解包代码从 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.

中处理带有尾部填充的结构的简单方法