упаковать любой тип данных в вектор <uint8_t>

0

Этот вопрос напоминает

сериализовать любой тип данных как вектор <uint8_t> - использовать reinterpret_cast?

template <typename T>
inline void pack (std::vector< uint8_t >& dst, T& data) {
    uint8_t * src = static_cast < uint8_t* >(static_cast < void * >(&data));
    dst.insert (dst.end (), src, src + sizeof (T));
}

распаковать

template <typename T>
inline void unpack (vector <uint8_t >& src, int index, T& data) {
    copy (&src[index], &src[index + sizeof (T)], &data);
}

Я пытаюсь упаковать любые типы данных в массив байтов.

q1: У меня есть утомительная реализация с использованием uint8_t *, я надеюсь, что выбор вектора является лучшим.

q2: Я не могу правильно упаковать std :: string с указанной выше функцией. Пожалуйста, дайте мне знать, насколько удобна вышеуказанная функция при упаковке всех типов данных

Пожалуйста, дайте мне знать, как включить std :: string в вышеупомянутый soluntion, т.е. pack и std :: string в вектор

Типы данных, которые я хочу упаковать:

все PODs std :: строковый вектор сам..

Внешняя проблема:

Я хочу упаковать класс, подобный этому, в массив байтов

class StartPeerSessionRequest : public Request {

public:
    StartPeerSessionRequest();
    virtual ~StartPeerSessionRequest();
    void composeRequestwithHardCodeValues();
    vector<uint8_t> packRequestWithTemplate();

private:
    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;

};

class Message {

public:
    Message();
    virtual ~Message();
    void composeMessage(vector<uint8_t> data, uint16_t opcode, uint16_t lengthOfData);

    uint16_t packetheader;
    uint16_t length;
    uint16_t request_response_id;
    uint16_t opcode;
    uint16_t checksum;
    vector<uint8_t> data;
}

Byte Array Тип данных, который я выбрал, является вектором (uint8_t)

Я хочу записать его в файл устройства или отправить через сеть bluetooth. Я не хочу десериализовать тот же класс, что и он. Я получаю ответ, который снова является байтовым массивом, и мне нужно в конечном итоге распаковать ответ другому классу

  • 2
    Если вам действительно нужно реализовать переносимую (без проводов, для разных машин) сериализацию, то изучите фреймворки, такие как буферы протокола или boost-сериализацию .
  • 0
    Вышеуказанная функция полезна только для типов POD. Если вы хотите написать код для сериализации / десериализации std :: string, вам придется это сделать. Это не сложно сделать, но правильный способ сделать это во многом зависит от вашей внешней проблемы - что вы планируете делать с этими векторами?
Показать ещё 1 комментарий
Теги:
vector
stdstring

1 ответ

4

tl; dr: Используйте библиотеку сериализации, такую как Boost.Serialization или Protocol Buffers.

Ad 1) Вектор в порядке. Изменение: но поток будет лучше.

Ad 2) Ну, вы не можете сериализовать объекты с косвенным образом таким образом, потому что вы получите только указатель на фактические данные, а не на сами данные. И вы можете сериализовать простые старые данные (стандартная компоновка в C++ 11); или, скорее, не гарантируется десериализационный объект, который не является обычным старым/стандартным макетом, приведет к созданию рабочего объекта. std::string (или любой другой контейнер) не является POD и содержит косвенность (std::string - это особый вид вектора).

Там нет никакого способа для сериализации/пакета произвольных объектов нестандартного-макета в массив байт без специальной поддержки. Либо вы должны писать функции сериализации и десериализации для каждого такого типа, либо вам нужно отказаться от требования к байтовому массиву и использовать что-то вроде boost :: any для сохранения информации о типе и правильного вызова конструкторов и деструкторов для вас за кулисами. Обратите внимание, что boost::any сам является объектом нестандартного макета с косвенностью.

Редактирование объявлений:

Я не хочу десериализовать тот же класс, что и он.

Да, да. На другом конце соединения. Таким образом, либо

  1. на другом конце используется одна и та же структура, и вам нужно написать сериализацию и десериализацию, один будет использоваться на одном конце, а другой на другом конце,
  2. на другом конце используется другая структура (возможно, даже на другом языке), и вы работаете с обеих сторон, поэтому вам нужно написать соответствующий сериализатор и десериализацию, или
  3. другой конец написан кем-то другим, и вы должны написать сериализацию для использования определенного согласованного формата.

Существуют тысячи способов сериализации каждого типа. Строка может быть сериализована как длина, а контент или контент, завершаемый указанным терминатором (обычно 0 байт), целое число (и размер строки - целое число) можно сериализовать в различное фиксированное количество байтов в разных порядках (в конце), использовать переменную кодирование длины и т.д.

И затем происходят изменения. Я вижу, что вы включили версию протокола. Но вам также нужно написать код десериализации, чтобы делать разные вещи на основе версии, что в общем случае означает, что это делается по-члену в любом случае (вы хотите вывести ту же структуру, независимую от версии, чтобы поддерживать нормальный код) и т.д.

Если у вас нет определенного протокола, я рекомендую вам посмотреть библиотеки Boost.Serialization и Protocol Buffers.

  • Boost.Serialization хорошо склеивается с существующими объектами, но специфичен для C++ и обеспечивает только обратную совместимость, то есть, если отправитель отправляет версию 2, а получатель не обновляется, сообщение не будет понято вообще.
  • Буферы протоколов требуют определения сообщений в нем специального формата и генерирования определения C++, но для большинства языков есть генераторы, и он поддерживает прямую совместимость, то есть, если отправитель отправляет версию 2, получатель будет понимать все поля, которые уже были в версии 1 и игнорировать те, которые не были.

Если по какой-то причине вы не можете их использовать (если только цель не ограничена, вы должны иметь возможность: я работаю над мобильным приложением, которое использует как Boost, так и Protobuf и работает на всех современных мобильных платформах), по крайней мере, прочитайте их технические описания и, возможно, посмотрите в коде, чтобы вы знали, как сделать сериализацию хорошо.

  • 0
    спасибо за вашу помощь, пожалуйста, устраните проблему сериализации / десериализации. Я просто хочу упаковать в массив байтов. а также распаковать другой байтовый массив в несколько типов данных. Пожалуйста, дайте мне знать любое общее читабельное решение спасибо
  • 0
    @MarshelAbraham: Просто подумайте, что я использовал слова «pack» / «unpack» вместо слов «serialize» / «deserialize»; они являются синонимами для этой цели.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню