Сериализация структур данных в C - PullRequest
41 голосов
/ 16 декабря 2008

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

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

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

Спасибо.


Результаты

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

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

Ответы [ 10 ]

16 голосов
/ 16 декабря 2008

Выезд tpl . Из обзора:

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

10 голосов
/ 16 декабря 2008

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

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

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

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

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

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

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


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


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


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

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?

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

6 голосов
/ 25 февраля 2013

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

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

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

4 голосов
/ 17 декабря 2008

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

3 голосов
/ 15 февраля 2011

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

3 голосов
/ 17 декабря 2008
2 голосов
/ 16 декабря 2008

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

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

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

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

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

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

1 голос
/ 13 ноября 2015

Вот пример использования библиотеки 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);
1 голос
/ 12 июня 2012

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

0 голосов
/ 04 ноября 2009

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

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

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