C ++序列化消息的方式?

时间:2011-11-15 15:02:54

标签: c++ serialization

在我目前的项目中,我有一些不同的接口,要求我将消息序列化为字节缓冲区。我觉得我可能不会以一种让真正的C ++程序员开心的方式来做这件事(而且我也愿意)。

我通常会这样做:

struct MyStruct {
    uint32_t x;
    uint64_t y;
    uint8_t  z[80];
};

uint8_t* serialize(const MyStruct& s) {
    uint8_t* buffer = new uint8_t[sizeof(s)];
    uint8_t* temp = buffer;
    memcpy(temp, &s.x, sizeof(s.x));
    temp += sizeof(s.x);

    //would also have put in network byte order...
    ... etc ...

    return buffer;
}

请原谅任何拼写错误,这只是我头脑中的一个例子。显然,如果我正在序列化的结构有内部指针,它会变得更复杂。

所以,我有两个密切相关的问题:

  1. 上面的具体方案是否存在任何问题,通过将结构直接转换为char缓冲区进行序列化,假设我知道目标系统具有相同的字节顺序?

  2. 主要问题:有没有更好......呃...... C ++?除了添加智能指针之外,还能做到这一点吗?我觉得这是一个常见的问题,STL可能会处理它 - 如果没有,我相信无论如何使用C ++机制都有更好的方法。

  3. 编辑如果您可以使用标准C ++ / STL以更好的方式更新序列化此结构,而不添加库,则可获得加分。

3 个答案:

答案 0 :(得分:6)

您应该可以直接使用Boost :: serialization或流。右侧链接中的更多信息。

Is it possible to serialize and deserialize a class in C++?

答案 1 :(得分:6)

您可能需要查看Google Protocol Buffers(也称为protobuf)。您可以使用语言中性IDL定义数据,然后通过生成器运行它以生成C ++类。它会处理字节排序问题,并且可以提供非常紧凑的二进制形式。

通过使用它,您不仅可以保存C ++数据,而且可以在其他语言(C#,Java,Python等)中使用,因为有可用的protobuf实现。

答案 2 :(得分:1)

刚刚投票选出AzPs作为答案,首先检查Boost是否可行。

另外还有关于您的代码示例:

1 - 将序列化功能的签名更改为采用文件的方法:

void MyStruct::serialize(FILE* file) // or stream
{
    int size = sizeof(this);
    fwrite(&size, sizeof(int), 1, file); // write size
    fwrite(this, 1, size, file);         // write raw bytes of struct
}

减少了复制结构的必要性。

2 - 是的,您的代码使序列化字节依赖于您的平台,编译器和编译器设置。这不是好事或坏事,如果相同的二进制文件写入和读取序列化字节,由于简单性和性能,这可能是有益的。但它不仅包括字节序,包装和结构布局也会影响兼容性。例如,您的应用程序的32位或64位版本将确保更改我们的结构的布局。最后,序列化原始足迹还会序列化填充字节 - 编译器可能在结构字段之间放置的字节,这对于高流量网络流来说是一种不利的开销(请参阅google协议缓冲区,因为它们可以保存每一点)。

编辑:

我看到你添加了“嵌入式”。是的,那么这样简单的序列化/反序列化(上面序列化的镜像实现)方法可能是一个很好而简单的选择。