Я пытаюсь сериализировать класс.
Определение класса:
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()
дает мне длину 87
На самом деле это должно дать мне 65 байтов. (Я посчитал, что вы можете понять это из конструктора)
Я подозреваю, что это добавление длины между ними.
Я пытался использовать text_archive
также это не работает.
Мне нужно просто сериализовать членов класса как есть.
Я думаю, мне нужно использовать некоторые черты или обертки.
пожалуйста, дайте мне знать
Спасибо
Итак, просто чтобы посмотреть, как я это сделаю, я попытался достичь оптимальных размеров, которые я рассчитал на обороте моей салфетки:
Я могу видеть, как вы ожидаете 57, 63 или 75 байтов
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-битный без знака).
Вот рабочее доказательство концепции: Жить на Колиру
generate()
Функция-член const generate делегирует работу вспомогательным функциям в отдельном пространстве имен:
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<unsigned char>
Например, boost::interprocess::containers::string<char, char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> >
,parse()
Метод разбора очень похож, за исключением того, что делегирует do_parse
перегрузки, чтобы сделать работу.
Программа испытаний туда-обратно со всеми возможными конфигурациями:
Как вы можете видеть, это даже не тот Возмутительно, что естественное решение Boost Serialization займет 107 байтов в моей системе (это всего на 8 байт больше, чем в моей последней конфигурации).
Отметим также, что, поскольку все генераторы Кармы используют любой выходной итератор, подключить его непосредственно в Низкоуровневые Операции Boost Archive для производительности и чтобы избежать выделения промежуточного хранилища.
Похоже, у вас есть очень специфические предположения о том, как Boost Serialization следует сериализовать в свой собственный непереносимый двоичный формат.
Ускоренная сериализация намного более высокого уровня, более или менее специально разработана для работы с данными, не относящимися к POD. Если вы настаиваете, вы сможете напрямую сериализовать массив вашего типа POD. В вашем вопросе, однако, класс совсем не POD и, следовательно, в любом случае не побитально сериализуемый.
Для переносных архивов см. EOS Portable Archive.
В Boost Archives есть дополнительные флаги, которые подавляют заголовок формата:
enum archive_flags {
no_header = 1, // suppress archive header info
no_codecvt = 2, // suppress alteration of codecvt facet
no_xml_tag_checking = 4 // suppress checking of xml tags - igored on saving
};
Увидеть Архив моделей
Вот справочная информация, чтобы увидеть, что вводит издержки по сравнению с простой побитовой сериализацией: