Python打包int32但不起作用?

时间:2015-05-16 18:23:30

标签: python c++ binary packing

我整天都在这,我似乎无法找到解决方案:(

我有一个我想要创建的文件的标题(我在Python中解析obj文件以输出到我的C ++游戏引擎中加载的二进制数据)。

这是Mesh Header的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基本上是来自stdint.h的uint32_t的typedef .... 因此,从这一点来看,前三个成员变量分别是2个字节,4个字节,2个字节,是吗?

这是我将其读入结构

的方式
fread(&_header, sizeof(MeshHeader), 1, f);

_vertex_size正确设置为56,但_vertex_count设置为65536.如果我将其数据类型更改为uint16(无符号短),则将其正确设置为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))

遵循struct.pack函数的规范(https://docs.python.org/2/library/struct.html)... H是无符号短(2个字节)I是无符号整数(4个字节),h是短(2个字节),它们完全匹配我在C MeshHeader类中指定的内容,不是吗?

过去几个小时我一直在掏出我的头发(而且我还没有留下太多的头发!)。有关可能发生的事情的任何建议吗?

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

1 个答案:

答案 0 :(得分:2)

正如@martineau所提到的,你所看到的是C struct packing。编译器在非字大小成员之间添加填充以优化内存访问。您可以使用某些#pragma指令禁用此功能。对于Visual C,语法为#pragma pack(1),如MSDN中所述。在以下示例中,我还使用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)

请注意,即使避免使用struct packing,您仍可能遇到endianity的问题。将结构写入磁盘假设您在编写器和读取器之前具有完全控制和知识。通过使用正确的序列化库,您可以使您的生活更轻松。有许多,但支持C和Python的一些示例是protobufAvro