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

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

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

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

Благодарю.


Результаты

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

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

Проверьте tpl . Из обзора:

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

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

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

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

  • Для указателя на другие объекты (например, 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 ?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Вот пример использования библиотеки 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); 
  • Как сериализовать объект в строку
  • Быстрая и компактная сериализация объектов в .NET.
  • Gson сериализует список полиморфных объектов
  • Преобразование данных формы в объект JavaScript с помощью jQuery
  • Настройте SparkContext с помощью sparkConf.set (..) при использовании искровой оболочки
  • В чем разница между использованием атрибута Serializable и внедрением ISerializable?
  • Зачем генерировать длинный serialVersionUID вместо простого 1L?
  • $ (this) .serialize () - Как добавить значение?
  • Что такое сериализация объектов?
  • Неверный регистр
  • Имеет ли значение то, что я выбираю для serialVersionUID при расширении classов Serializable в Java?
  • Давайте будем гением компьютера.