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

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

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

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

Спасибо.


Полученные результаты

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
44
0
42 218
10

Ответы 10

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

Tpl is a library for serializing C data. The data is stored in its natural binary form. The API is small and tries to stay "out of the way". Compared to using XML, tpl is faster and easier to use in C programs. Tpl can serialize many C data types, including structures.

Tpl, похоже, не поддерживает вложенные структуры. Например, узел, который может содержать два подузла.

Daniel Lucraft 16.12.2008 17:47

Еще одна проблема с tpl - ограниченная переносимость поплавков.

eadmaster 22.12.2012 11:45

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

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

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

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

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

Вы можете узнать больше о матрице смежности здесь: http://en.wikipedia.org/wiki/Modified_adjacency_matrix

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

Daniel Lucraft 16.12.2008 17:50

Дерево - это просто частный случай графа, и, имея круговые ссылки, можно утверждать, что на самом деле у вас есть граф, а не дерево.

mmattax 16.12.2008 18:15

Хорошо: все структуры данных C можно рассматривать как графики памяти. Есть ли библиотека, которая может сериализовать эти данные?

Daniel Lucraft 16.12.2008 18:19

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

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

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

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

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

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

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


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


[1] КОРЕНЬ использует этот механизм для обеспечения очень гибкой поддержки сериализации в 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?

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

Спасибо за отличную запись. По сути, этот план был у меня в голове как «доказательство существования» библиотеки. Теоретически каждая библиотека, которую можно представить на C, была написана. Не могу поверить, что этого не существует. Я могу попробовать написать эту вещь на Рождество.

Daniel Lucraft 17.12.2008 11:15

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

http://s11n.net/c11n/

HTH

Ссылка не работает.

Trevor Hickey 18.01.2017 22:39

Работает сейчас. Заголовок "libc11n: библиотека / фреймворк сериализации для C", sf ссылка: sourceforge.net/projects/s11n

domen 15.03.2017 17:05

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

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

Правда. Однако YAML C++ сериализует структуры данных C, несмотря на то, что для этого требуется компилятор C++. Другие читатели SO могут найти это полезным.

AndyL 10.06.2013 21:58

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

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

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

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

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

Это работало очень хорошо даже для вложенных древовидных структур, хотя для его компиляции потребовались некоторые изменения в коде. Отсутствует include для time.h и предполагаемый typedef для ushort, который не является стандартом языка.

danny 17.03.2017 20:35

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

danny 17.03.2017 20:35

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

  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);

Другие вопросы по теме