Сериализация структур данных в C

Мне нужна библиотека C, которая может сериализовать мои структуры данных на диск, а затем загрузить их позже. Он должен принимать произвольно вложенные структуры, возможно с круговыми ссылками.

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

Примечание. Меня не интересует переносимость данных. Я хотел бы использовать его в качестве кеша, поэтому я могу полагаться на среду, которая не меняется.

Спасибо.


Результаты

Кто-то предложил Tpl, который является удивительной библиотекой, но я считаю, что он не выполняет произвольные графы объектов, такие как дерево Узлы, каждая из которых содержит два других узла.

Другим кандидатом является Eet, который является проектом диспетчера окон Просвещения. Выглядит интересно, но, опять же, кажется, не имеет возможности сериализовать вложенные структуры.

Ответ 1

Отъезд tpl. Из обзора:

Tpl - это библиотека для сериализации C данные. Данные хранятся в естественная двоичная форма. API небольшой и пытается остаться "с дороги". По сравнению с использованием XML, tpl быстрее и проще в использовании в программах на C. Tpl может сериализовать многие типы данных C, включая структуры.

Ответ 2

Я знаю, что вы просите библиотеку. Если вы не можете найти его (:: boggle::, вы думаете, что это была проблема!), Вот схема решения:

Вы должны иметь возможность написать генератор кода [1], чтобы сериализовать деревья/графики без предварительной обработки (простое выполнение).

Вам нужно проанализировать структуру node (typedef обработка?) и записать введенные значения данных в прямом порядке, но с осторожностью относиться к указателям.

  • Для указателя на другие объекты (т.е. char *name;), которые, как вы знаете, указаны отдельно, вы можете сериализовать целевые данные напрямую.

  • Для объектов, которые можно многократно перенаправить, а для других узлов вашего дерева вам придется представлять структуру указателя. Каждому объекту присваивается номер сериализации, который является тем, что выписано на месте указателя. Поддерживайте структуру перевода между текущей ячейкой памяти и номером сериализации. При обнаружении указателя посмотрите, присвоено ли ему уже определенное число, если нет, дайте ему один и поставите этот объект для сериализации.

Для чтения также требуется шаг перевода node - #/memory-location, и может быть проще сделать в два прохода: регенерировать узлы с номерами node в слотах указателя (плохой указатель, быть предупрежденным) чтобы узнать, куда поместится каждый node, затем пройдите по структуре, снова фиксируя указатели.

Я ничего не знаю о tpl, но вы могли бы с этим справиться.


Формат на диске/сети, вероятно, должен быть обрамлен некоторой информацией о типе. Вам понадобится схема смены имен.


[1] ROOT использует этот механизм для обеспечения очень гибкой поддержки сериализации в С++.


Позднее добавление: Мне кажется, что это не всегда так просто, как я подразумевал выше. Рассмотрим следующую (надуманную и плохо спроектированную) декларацию:

enum {
   mask_none = 0x00,
   mask_something = 0x01,
   mask_another = 0x02,
   /* ... */
   mask_all = 0xff
};
typedef struct mask_map {
   int mask_val;
   char *mask_name;
} mask_map_t;
mask_map_t mask_list[] = {
   {mask_something, "mask_something"},
   {mask_another, "mask_another"},
   /* ... */
};
struct saved_setup {
   char* name;
   /* various configuration data */
   char* mask_name;
   /* ... */
};

и предположим, что мы инициализируем элементы struct saved_setup, чтобы mask_name указывал на mask_list[foo].mask_name.

Когда мы переходим к сериализации данных, что мы делаем с struct saved_setup.mask_name?

Вам нужно будет позаботиться о разработке структур данных и/или привнести в процесс сериализации определенный случайный анализ.

Ответ 3

Это мое решение. Он использует мою собственную реализацию системных вызовов malloc, free и mmap, munmap. Следуйте приведенным примерам кодов. Ссылка: http://amscata.blogspot.com/2013/02/serialize-your-memory.html

В моем подходе я создаю массив char как свое собственное пространство RAM. Тогда есть функции для выделения памяти и освобождения. После создания структуры данных, используя mmap, я пишу массив char в файл.

Всякий раз, когда вы хотите загрузить его обратно в память, есть функция, которая использовала munmap, чтобы снова разместить структуру данных в массиве char. Поскольку у вас есть виртуальные адреса для ваших указателей, вы можете использовать свою структуру данных. Это означает, что вы можете создать структуру данных, сохранить ее, загрузить, снова отредактировать и снова сохранить.

Ответ 4

Вы можете посмотреть eet. Библиотека проекта просвещения для хранения типов данных C (включая вложенные структуры). Хотя почти все библиотеки проекта просвещения находятся в предварительном альфа-состоянии, eet уже выпущен. Я не уверен, однако, если он может обрабатывать круговые ссылки. Наверное, нет.

Ответ 6

вы должны проверить gwlib. сериализатор/десериализатор обширен. и есть обширные тесты, доступные для просмотра. http://gwlib.com/

Ответ 7

Я предполагаю, что вы говорите о хранении структуры графа, если не игнорировать...

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

Это имеет три преимущества (которые могут или не имеют значения в вашем приложении):

  • матрица смежности - очень естественный способ создания и хранения графика
  • Вы можете создать матрицу смежности и импортировать их в свои приложения.
  • Вы можете хранить и читать ваши данные значимым образом.

Я использовал этот метод во время проекта CS и определенно, как бы я сделал это снова.

Подробнее о матрице смежности вы можете прочитать здесь: http://en.wikipedia.org/wiki/Modified_adjacency_matrix

Ответ 8

Другим вариантом является Avro C, реализация Apache Avro в C.

Ответ 9

В теории YAML должен делать то, что вы хотите http://code.google.com/p/yaml-cpp/

Пожалуйста, дайте мне знать, если это сработает для вас.

Ответ 10

Вот пример, используя библиотеку Binn (мое творение):

  binn *obj;

  // create a new object
  obj = binn_object();

  // add values to it
  binn_object_set_int32(obj, "id", 123);
  binn_object_set_str(obj, "name", "Samsung Galaxy Charger");
  binn_object_set_double(obj, "price", 12.50);
  binn_object_set_blob(obj, "picture", picptr, piclen);

  // send over the network
  send(sock, binn_ptr(obj), binn_size(obj));

  // release the buffer
  binn_free(obj);

Если вы не хотите использовать строки как ключи, вы можете использовать binn_map, который использует целые числа в качестве ключей.

Существует также поддержка списков, и все эти структуры могут быть вложенными:

  binn *list;

  // create a new list
  list = binn_list();

  // add values to it
  binn_list_add_int32(list, 123);
  binn_list_add_double(list, 2.50);

  // add the list to the object
  binn_object_set_list(obj, "items", list);

  // or add the object to the list
  binn_list_add_object(list, obj);