升压序列化二进制归档给予不正确的输出 [英] Boost Serialization Binary Archive giving incorrect output

查看:204
本文介绍了升压序列化二进制归档给予不正确的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图序列化类。

类定义:

 类StartPeerSessionRequest {
上市:
    StartPeerSessionRequest();
    虚拟〜StartPeerSessionRequest();
    虚空composeRequestwithHard codeValues​​();
    无效保存();
    stringstream的serializedRequest;
    / *的boost ::系列化:: binary_object serlreq; * /私人的:
    StartPeerSessionRequest(常量StartPeerSessionRequest&安培;);    uint16_t mProtocolVersion;
    uint16_t mSessionFlags;
    uint16_t mMaxResponseLength;
    串mMake;
    串模型探讨;
    串mSerialNumber;
    uint8_t有mTrackDelay;
    串mHeadUnitModel;
    串mCarModelYear;
    串MVIN;
    uint16_t mVehicleMileage;
    uint8_t有mShoutFormat;
    uint8_t有mNotificationInterval;    友元类的boost ::系列化::访问;
    模板< typename的归档和GT;无效连载(归档和放大器; AR,const的无符号整型版);
};StartPeerSessionRequest :: StartPeerSessionRequest(){    mProtocolVersion = 1 * 10000 + 14 * 100 + 4;
    mSessionFlags = 1;
    mMaxResponseLength = 0;
    mMake =MyMake;
    模型探讨=为MyModel;
    mSerialNumber =10000;
    mTrackDelay = 0;
    mHeadUnitModel =音响本体;
    mCarModelYear =2014;
    MVIN =1234567980;
    mVehicleMileage = 1000;
    mShoutFormat = 3;
    mNotificationInterval = 1;
}模板<类归档和GT;无效StartPeerSessionRequest ::连载(归档和放大器; AR,const的无符号整型版){
    AR&安培; mProtocolVersion;
    AR&安培; mSessionFlags;
    AR&安培; mMaxResponseLength;
    AR&安培; mMake;
    AR&安培;模型探讨;
    AR&安培; mSerialNumber;
    AR&安培; mTrackDelay;
    AR&安培; mHeadUnitModel;
    AR&安培; mCarModelYear;
    AR&安培; MVIN;
    AR&安培; mVehicleMileage;
    AR&安培; mShoutFormat;
    AR&安培; mNotificationInterval;
}无效StartPeerSessionRequest ::保存(){
    提高::档案:: binary_oarchive OA(serlreq,提振::档案:: no_header);
    OA<< (*这个);
    / * COUT<<\\ n binary_oarchive:<< serlreq.size(); * /    提高::档案:: text_oarchive的OTA(serializedRequest,提振::档案:: no_header);
    OTA<< (*这个);
    COUT<< \\ n text_oarchive:<< serializedRequest.str()&所述;&下; 大小:<< serializedRequest.str()的大小()。
}

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

其实应该给我65个字节。 (我数u能明白这一点从构造)

我怀疑它是介于两者之间的长度追加

我已经尝试使用 text_archive 也是它不工作。

我需要的是只是简单的序列化类成员,因为它是。

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

请让我知道

感谢


解决方案

好了,所以,就看我怎么会做,我试图达到最佳尺寸我算了算<一个href=\"http://stackoverflow.com/questions/26556145/boost-serialization-binary-archhive-giving-incorrect-output#comment41745393_26556145\">on我的餐巾背面:


  

我可以看到你是如何想到57,63,或75字节

  mProtocolVersion = 1 * 10000 + 14 * 100 + 4; // 2字节
mSessionFlags = 1; // 2字节
mMaxResponseLength = 0; // 2字节
mMake =MyMake; // 6个字节长度+
模型探讨=为MyModel; // 7个字节长度+
mSerialNumber =10000; // 5个字节长度+
mTrackDelay = 0; // 1字节
mHeadUnitModel =音响本体; // 8字节长度+
mCarModelYear =2014; // 4个字节长度+
MVIN =1234567980; // 10个字节长度+
mVehicleMileage = 1000; // 2字节
mShoutFormat = 3; // 1字节
mNotificationInterval = 1; // 1字节
// // -------------------------------------- 51个字节+ 6×长度


在这种情况下,我创建二进制序列化code。使用升压精神(噶序列化和齐作反序列化)。我做了长度字段的配置规模(8,16,32或64位无符号)。

下面是一个概念证明工作: 住在Coliru

生成()

该常量生成成员函数的代表在一个单独的命名空间中的工作,辅助功能:

 模板&LT; typename的集装箱&GT;
布尔生成(集装箱和放大器;字节)const的{
    自动出=的std :: back_inserter(字节);    使用my_serialization_helpers :: do_generate;
    返回do_generate(满分,mProtocolVersion)
        &功放;&安培; do_generate(出,mSessionFlags)
        &功放;&安培; do_generate(出,mMaxResponseLength)
        &功放;&安培; do_generate(出,mMake)
        &功放;&安培; do_generate(出,模型探讨)
        &功放;&安培; do_generate(出,mSerialNumber)
        &功放;&安培; do_generate(出,mTrackDelay)
        &功放;&安培; do_generate(出,mHeadUnitModel)
        &功放;&安培; do_generate(出,mCarModelYear)
        &功放;&安培; do_generate(出,MVIN)
        &功放;&安培; do_generate(出,mVehicleMileage)
        &功放;&安培; do_generate(出,mShoutFormat)
        &功放;&安培; do_generate(出,mNotificationInterval);
}

注意


  • do_generate 重载可以随意根据需要为未来的加类型

  • 容器可以很容易地从例如切换的std ::矢量&lt; unsigned char型&GT; ,例如要的boost ::进程间::容器::字符串&LT;焦炭,char_traits&LT;焦炭&gt;中的boost ::进程间::分配器&LT;焦炭,提高::进程间:: managed_shared_memory :: segment_manager&GT;方式&gt;

解析()

解析方法不同的是它委托给非常相似 do_parse 重载做的工作。

测试

测试程序与所有可能的配置来回:


  • 8位长度字段, 网57字节 与升压系列化:70

  • 16位的长度字段, 网63字节 与升压系列化:76

  • 32位的长度字段, 网75个字节 与升压系列化:88

  • 64位的长度字段, 网99字节 与升压系列化:112

正如你可以看到它甚至不是的的离谱的是,自然加速系列化解决方案,<一个href=\"http://stackoverflow.com/questions/26556145/boost-serialization-binary-archhive-giving-incorrect-output#comment41736250_26556145\">would采取我的系统 107字节(这比我上次配置的只有8个字节)。

还要注意,由于噶发电机全部采取任何输出迭代器,它应该是比较容易直接接线入低级别提升归档操作 性能和避免分配中间存储。

I am trying to Serialize a class.

Class definition:

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<<"\n binary_oarchive :"<<serlreq.size();*/

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

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

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.

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.

Please let me know

Thanks

解决方案

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:

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

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).

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

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);
}

Note that

  • 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()

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

Testing

The test program roundtrips with all possible configurations:

  • 8-bit length field, net 57 bytes, with boost serialization: 70
  • 16-bit length field, net 63 bytes, with boost serialization: 76
  • 32-bit length field, net 75 bytes, with boost serialization: 88
  • 64-bit length field, net 99 bytes, with boost serialization: 112

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).

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.

这篇关于升压序列化二进制归档给予不正确的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆