C ++ способ сериализации сообщения? - PullRequest
3 голосов
/ 15 ноября 2011

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

Я бы обычно делал что-то вроде этого:

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. Есть ли какие-либо проблемы в конкретном сценарии, приведенном выше, с сериализацией, приводящей структуру непосредственно к буферу символов, предполагая, что я знаю, что системы назначения находятся в том же порядке байтов?

  2. Основной вопрос: Есть ли лучший ... эм ... C ++? способ сделать это помимо добавления умных указателей? Я чувствую, что это настолько распространенная проблема, что STL, вероятно, справится с этим - и если это не так, я уверен, что есть лучший способ сделать это в любом случае, используя механизмы C ++.

РЕДАКТИРОВАТЬ Бонусные баллы, если вы можете сделать чистый пример сериализации этой структуры лучшим способом, используя стандартный C ++ / STL без добавления библиотек.

Ответы [ 3 ]

6 голосов
/ 15 ноября 2011

Возможно, вы захотите взглянуть на Google Protocol Buffers (также известный как protobuf). Вы определяете свои данные в независимом от языка IDL и затем запускаете их через генератор для генерации ваших классов C ++. Он позаботится о проблемах с порядком байтов и может предоставить очень компактную двоичную форму.

Используя это, вы не только сможете сохранить свои данные C ++, но и использовать их на других языках (C #, Java, Python и т. Д.), Поскольку для них доступна реализация protobuf. * ​​1005 *

6 голосов
/ 15 ноября 2011

Возможно, вы должны использовать либо Boost :: serialization, либо потоки напрямую. Больше информации в любой из ссылок справа.

Можно ли сериализовать и десериализовать класс в C ++?

1 голос
/ 15 ноября 2011

только что проголосовали 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, так как они ищут каждый бит, который могут сохранить).:

я вижу, вы добавили "встроенный".да, тогда такие простые методы сериализации / десериализации (зеркальная реализация вышеописанной сериализации) могут быть хорошим и простым выбором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...