Как мне написать сериализатор на C, используя MessagePack (Mpack)

#c #msgpack #messagepack

#c #msgpack #messagepack

Вопрос:

Я хотел бы написать приложение-сериализатор, которое будет кодировать любой тип структуры данных C в формат MessagePack. Все примеры, которые я видел, показывают кодирование известных структур, подобных этой, с использованием MPack:

 // encode to memory buffer
char* data;
size_t size;
mpack_writer_t writer;
mpack_writer_init_growable(amp;writer, amp;data, amp;size);

// write the example on the msgpack homepage
mpack_start_map(amp;writer, 2);
mpack_write_cstr(amp;writer, "compact");
mpack_write_bool(amp;writer, true);
mpack_write_cstr(amp;writer, "schema");
mpack_write_uint(amp;writer, 0);
mpack_finish_map(amp;writer);

// finish writing
if (mpack_writer_destroy(amp;writer) != mpack_ok) {
    fprintf(stderr, "An error occurred encoding the data!n");
    return;
}

// use the data
do_something_with_data(data, size);
free(data);
  

Но чего бы я хотел, так это иметь возможность кодировать любую структуру данных C. Например, если бы у меня было следующее:

 struct My_Struct{
  int   number1;
  float number2;
  char array[6];
};

struct My_Struct ms = {10, 4.44, "Hello"};
  

откуда мне программно знать, что первые 4 байта представляют собой int, чтобы я мог вызвать функцию mpack_write_int, чтобы начать упаковку int в формат messagepack?

Комментарии:

1. Вам нужно вызвать функцию записи для каждого элемента структуры вручную. C не предоставляет автоматизации для этого. Однако есть одна идея: Если вам нужно написать много из них, вы могли бы записать эти определения в текстовые файлы в некотором формате, а затем использовать язык сценариев, который генерировал бы определения структуры и функции кодирования / декодирования для вас. Возможно, такого рода инструменты уже существуют.

2. @user694733, я понимаю, что мне нужно будет вызвать функцию записи для массивов int, float и char, но откуда мне знать, что ms изначально содержит эти типы?

3. Единственный способ узнать это — проверить определение структуры вручную. В C нет метода для перечисления структуры во время выполнения. Итак, вам нужно будет написать функцию кодирования для каждого типа структуры отдельно, например void encode_my_struct_with_mpack(mpack_writer_t * writer, struct My_Struct ms) { /* call mpack write functions here */ }

4. вы можете увидеть, как это реализовано в исходных текстах msgpack, потому что msgpack может кодировать пользовательские структуры и классы. смотрите примеры в msgpack-c/blob/master/test/object.cpp и msgpack-c/blob/master/test/user_class.cpp