2

我正在尝试编写一个 Python C 扩展来读取打包的二进制数据(它存储为结构的结构),然后将其解析为 Python 对象。在 32 位机器上一切正常(二进制文件总是写在 32 位架构上),但不是在 64 位机器上。有这样做的“首选”方式吗?


要发布很多代码,但作为示例:

struct
{
    WORD    version;
    BOOL    upgrade;
    time_t  time1;
            time_t  time2;
} apparms;

File *fp;
fp = fopen(filePath, "r+b");
fread(&apparms, sizeof(apparms), 1, fp);
return Py_BuildValue("{s:i,s:l,s:l}",
  "sysVersion",apparms.version,
  "powerFailTime", apparms.time1,
  "normKitExpDate", apparms.time2
 );

现在在 32 位系统上这很好用,但在 64 位上,我的 time_t 大小不同(32 位与 64 位长)。


该死的,你们这些人速度很快。

帕特里克,我最初开始使用 struct 包,但发现它只是为了满足我的需要而减慢速度。另外,我正在寻找编写 Python 扩展的借口。

我知道这是一个愚蠢的问题,但我需要注意哪些类型?

谢谢。

4

5 回答 5

4

明确指定您的数据类型(例如整数)是 32 位的。否则,如果您在读取它们时有两个相邻的整数,它们将被读取为一个 64 位整数。

当您处理跨平台问题时,需要注意的两个主要事项是:

  1. 位。如果您的打包数据是用 32 位整数写入的,那么您的所有代码在读写时都必须明确指定 32 位整数
  2. 字节顺序。如果您将代码从 Intel 芯片移动到 PPC 或 SPARC,您的字节顺序将是错误的。您必须导入数据,然后对其进行字节翻转,以使其与当前架构相匹配。否则 12 ( 0x0000000C) 将被读取为 201326592 ( 0x0C000000)。

希望这会有所帮助。

于 2008-09-25T19:07:22.487 回答
2

'struct' 模块应该能够做到这一点,尽管数据中间的结构对齐总是一个问题。但是,要做到这一点并不难:找出(一次)structs-in-structs 对齐的边界,然后填充(手动,使用“x”说明符)到该边界。您可以通过将 struct.calcsize() 与您的实际数据进行比较来仔细检查您的填充。这肯定比为其编写 C 扩展更容易。

为了像这样继续使用 Py_BuildValue(),您有两个选择。您可以在编译时确定 time_t 的大小(就基本类型而言,即“an int”或“a long”或“an ssize_t”),然后对 Py_BuildValue 使用正确的格式字符——“i”表示 int, 'l' 表示长,'n' 表示 ssize_t。或者您可以手动使用 PyInt_FromSsize_t(),在这种情况下,编译器会为您进行向上转换,然后使用“O”格式字符将结果传递给 Py_BuildValue。

于 2008-09-25T19:03:02.777 回答
2

您需要确保为您的结构使用与体系结构无关的成员。例如,一个 int 在一种架构上可能是 32 位,而在另一种架构上可能是 64 位。正如其他人所建议的那样,请改用int32_t样式类型。如果您的结构包含未对齐的成员,您可能还需要处理编译器添加的填充。

跨架构数据的另一个常见问题是字节序。Intel i386 架构是little-endian,但如果您在完全不同的机器(例如Alpha 或Sparc)上阅读,您也必须担心这一点。

Python struct 模块使用作为格式字符串的一部分传递的前缀来处理这两种情况。

  • @ - 使用原生大小、字节序和对齐方式。i= sizeof(int), l= sizeof(long)
  • = - 使用原生字节序,但标准大小和对齐方式(i=32 位,l=64 位)
  • < - Little-endian 标准尺寸/对齐方式
    • Big-endian 标准尺寸/对齐方式

一般来说,如果数据从你的机器上传递过来,你应该将字节顺序和大小/填充格式确定为特定的东西——即。使用“<”或“>”作为您的格式。如果你想在你的 C 扩展中处理这个,你可能需要添加一些代码来处理它。

于 2008-09-25T19:15:52.700 回答
1

你读取二进制数据的代码是什么?确保将数据复制到适当大小的类型中,例如int32_t而不是int.

于 2008-09-25T19:02:00.940 回答
0

你为什么不使用struct包?

于 2008-09-25T19:02:20.550 回答