将解压代码从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 S
  • L15 S2
  • L 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 中处理带有尾随填充的结构的简单方法。


以上是将解压代码从perl转换为python的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>