Python 打包 int32 但不起作用?

Python Packing int32 but doesn't work?

本文关键字:不起作用 int32 打包 Python      更新时间:2023-10-16

我已经纠结了一天了,但似乎找不到解决办法。

我有一个我想要创建的文件的头文件(我正在解析Python中的obj文件,以输出为二进制数据,以便在我的c++游戏引擎中加载)。

下面是网格头的c++定义

struct MeshHeader
{
    unsigned short _vertex_size;
    uint32 _vertex_count;
    unsigned short _index_buffer_count;
    short _position_offset;
    unsigned short _position_component_count;
    short _uv_offset;
    unsigned short _uv_component_count;
    short _normal_offset;
    unsigned short _normal_component_count;
    short _tangent_offset;
    unsigned short _tangent_component_count;
    short _binormal_offset;
    unsigned short _binormal_component_count;
    short _colour_offset;
    unsigned short _colour_component_count;
};

其中uint32基本上是来自stint .h....的uint32_t的类型定义所以从这里判断,前三个成员变量分别是2字节,4字节,2字节,对吗?

我是这样把它读入结构

fread(&_header, sizeof(MeshHeader), 1, f);

_vertex_size被正确设置为56,但_vertex_count被设置为65536。如果我将其数据类型更改为uint16 (unsigned short),它将被正确设置为36。但是为什么呢?我正在使用pack("<I")函数(知道我的机器是小端序)。

这是我在python中的打包代码

    f.write(pack('<H', self._vertex_size))
    f.write(pack('<I', self._vertex_count))
    f.write(pack('<H', self._index_buffer_count))
    f.write(pack('<h', self._position_offset))
    f.write(pack('<H', self._position_component_count))
    f.write(pack('<h', self._uv_offset))
    f.write(pack('<H', self._uv_component_count))
    f.write(pack('<h', self._normal_offset))
    f.write(pack('<H', self._normal_component_count))
    f.write(pack('<h', self._tangent_offset))
    f.write(pack('<H', self._tangent_component_count))
    f.write(pack('<h', self._binormal_offset))
    f.write(pack('<H', self._binormal_component_count))
    f.write(pack('<h', self._colour_offset))
    f.write(pack('<H', self._colour_component_count))

遵循结构的规范。包功能(https://docs.python.org/2/library/struct.html)…H是无符号短(2字节)我是无符号整数(4字节)和H是一个短(2字节),它完全匹配我在我的C MeshHeader类中指定的,不是吗?

过去几个小时我一直在拔我的头发(我的头发已经不多了!)对可能发生的事情有什么建议吗?

这是Sublime Text 3中头文件的快照http://gyazo.com/e15942753819e695617390129e6aa879

正如@martineau所提到的,您所看到的是C结构体打包。编译器在非字长成员之间添加填充以优化内存访问。您可以使用某些#pragma指令禁用此功能。对于Visual C,语法是MSDN中解释的#pragma pack(1)。在下面的示例中,我还使用pushpop将包装恢复到以前的值。正确的封装对于有效的内存访问非常重要,因此更改它应该只保留到您写入磁盘的结构。

// align on 1-byte
#pragma pack(push, 1)
struct MeshHeader
{
    unsigned short _vertex_size;
    uint32 _vertex_count;
    unsigned short _index_buffer_count;
    short _position_offset;
    // ...
};
// restore alignment
#pragma pack(pop)

请注意,即使避免了结构打包,您仍然可能遇到顺序问题。将结构写入磁盘假定您对写入器和读取器都有完全的控制和提前的知识。您可以通过使用适当的序列化库来简化您的工作。有很多,但支持C和Python的例子只有protobuf和Avro。