Boost Serialization Binary Archive 给出不正确的输出

我正在尝试序列化一个类.

I am trying to Serialize a class.

类定义:

class StartPeerSessionRequest {
public:
    StartPeerSessionRequest();
    virtual ~StartPeerSessionRequest();
    void composeRequestwithHardCodeValues();
    void save();
    stringstream serializedRequest;
    /*boost::serialization::binary_object serlreq;*/

private:
    StartPeerSessionRequest(const StartPeerSessionRequest &);

    uint16_t mProtocolVersion;
    uint16_t mSessionFlags;
    uint16_t mMaxResponseLength;
    string   mMake;
    string   mModel;
    string   mSerialNumber;
    uint8_t  mTrackDelay;
    string   mHeadUnitModel;
    string   mCarModelYear;
    string   mVin;
    uint16_t mVehicleMileage;
    uint8_t  mShoutFormat;
    uint8_t  mNotificationInterval;

    friend class boost::serialization::access;
    template <typename Archive> void serialize(Archive &ar, const unsigned int version);
};

StartPeerSessionRequest::StartPeerSessionRequest() {

    mProtocolVersion      = 1 * 10000 + 14 * 100 + 4;
    mSessionFlags         = 1;
    mMaxResponseLength    = 0;
    mMake                 = "MyMake";
    mModel                = "MyModel";
    mSerialNumber         = "10000";
    mTrackDelay           = 0;
    mHeadUnitModel        = "Headunit";
    mCarModelYear         = "2014";
    mVin                  = "1234567980";
    mVehicleMileage       = 1000;
    mShoutFormat          = 3;
    mNotificationInterval = 1;
}

template <class Archive> void StartPeerSessionRequest::serialize(Archive &ar, const unsigned int version) {
    ar & mProtocolVersion;
    ar & mSessionFlags;
    ar & mMaxResponseLength;
    ar & mMake;
    ar & mModel;
    ar & mSerialNumber;
    ar & mTrackDelay;
    ar & mHeadUnitModel;
    ar & mCarModelYear;
    ar & mVin;
    ar & mVehicleMileage;
    ar & mShoutFormat;
    ar & mNotificationInterval;
}

void StartPeerSessionRequest::save() {
    boost::archive::binary_oarchive oa(serlreq, boost::archive::no_header);
    oa << (*this);
    /*cout<<"
 binary_oarchive :"<<serlreq.size();*/

    boost::archive::text_oarchive ota(serializedRequest, boost::archive::no_header);
    ota << (*this);
    cout << "
 text_oarchive :" << serializedRequest.str() << "size :" << serializedRequest.str().size();
}

serializedRequest.str.size() 为我提供了 87 的长度

serializedRequest.str.size() provides me a length of 87

实际上它应该为我提供 65 个字节.(我数过你可以从构造函数中算出来)

Actually it should provide me 65 bytes. (I've counted u can figure that out from the constructor)

我怀疑它在中间附加了长度.

I suspect it is appending lengths in between.

我试过使用 text_archive 也没有用.

I have tried using text_archive also it doesnt work.

我需要的是按原样简单地序列化类成员.

What I need is to just plain serialize class members as it is.

我想我需要使用一些特征或包装器.

I guess i need to use some traits or wrappers.

请告诉我

谢谢

推荐答案

好吧,为了看看我会怎么做,我已经尝试达到我计算出的最佳尺寸 在我的餐巾背面:

Okay, so, just to see how I'd do, I've tried to reach the optimum sizes I calculated on the back of my napkin:

我可以看出您对 57、63 或 75 个字节的期望

I can see how you'd expect 57, 63, or 75 bytes

mProtocolVersion      = 1*10000+14*100+4; // 2 bytes
mSessionFlags         = 1;                // 2 bytes
mMaxResponseLength    = 0;                // 2 bytes
mMake                 = "MyMake";         // 6 bytes + length
mModel                = "MyModel";        // 7 bytes + length
mSerialNumber         = "10000";          // 5 bytes + length
mTrackDelay           = 0;                // 1 byte
mHeadUnitModel        = "Headunit";       // 8 bytes + length
mCarModelYear         = "2014";           // 4 bytes + length
mVin                  = "1234567980";     // 10 bytes + length
mVehicleMileage       = 1000;             // 2 byte
mShoutFormat          = 3;                // 1 byte
mNotificationInterval = 1;                // 1 byte
// -------------------------------------- // 51 bytes + 6 x length

在本例中,我使用 Boost Spirit 创建了二进制序列化代码(用于序列化的 Karma 和用于反序列化的 Qi).我将长度字段的大小设置为可配置(8、16、32 或 64 位无符号).

In this instance, I created binary serialization code using Boost Spirit (Karma for serialization and Qi for de-serialization). I made the size of the length field configurable (8,16,32 or 64 bit unsigned).

这是一个有效的概念证明:生活在 Coliru

Here's a working proof of concept: Live On Coliru

const generate 成员函数将工作委托给单独命名空间中的辅助函数:

The const generate member function delegates the work to helper functions in a separate namespace:

template <typename Container>
bool generate(Container& bytes) const {
    auto out = std::back_inserter(bytes);

    using my_serialization_helpers::do_generate;
    return do_generate(out, mProtocolVersion)
        && do_generate(out, mSessionFlags)
        && do_generate(out, mMaxResponseLength)
        && do_generate(out, mMake)
        && do_generate(out, mModel)
        && do_generate(out, mSerialNumber)
        && do_generate(out, mTrackDelay)
        && do_generate(out, mHeadUnitModel)
        && do_generate(out, mCarModelYear)
        && do_generate(out, mVin)
        && do_generate(out, mVehicleMileage)
        && do_generate(out, mShoutFormat)
        && do_generate(out, mNotificationInterval);
}

注意

  • do_generate 可以根据未来类型的需要自由添加重载
  • 容器可以轻松切换,例如std::vector,例如boost::interprocess::containers::string, boost::interprocess::allocator>.
  • do_generate overloads can be freely added as required for future types
  • the container can easily be switched from e.g. std::vector<unsigned char>, to e.g. boost::interprocess::containers::string<char, char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> >.

parse 方法非常相似,只是它委托给 do_parse 重载来完成工作.

The parse method is very similar except it delegates to do_parse overloads to do the work.

测试程序使用所有可能的配置进行往返:

The test program roundtrips with all possible configurations:

  • 8 位长度字段,净 57 字节,使用 boost 序列化:70
  • 16 位长度字段,净 63 字节,使用 boost 序列化:76
  • 32 位长度字段,净 75 字节,使用 boost 序列化:88
  • 64 位长度字段,净 99 字节,带有增强序列化:112

如您所见,自然的 Boost 序列化解决方案 将在我的系统上占用 107 个字节(仅比我上次配置多 8 个字节).

As you can see it's not even that outrageous that the natural Boost Serialization solution would take 107 bytes on my system (it's only 8 bytes more than my last configuration).

还要注意,由于 Karma 生成器都采用任何输出迭代器,因此将其直接连接到 低级 Boost Archive 操作,以提高性能并避免分配中间存储.

Note also, that since the Karma generators all take any output iterator, it should be relatively easy to wire it directly into the low-level Boost Archive operations for performance and to avoid allocating intermediate storage.

相关文章