在C中序列化数据结构

我想要一个C库,可以序列化我的数据结构到磁盘,然后再加载它们。 它应该接受任意嵌套的结构,可能带有循环引用。

我认为这个工具需要一个描述我的数据结构的configuration文件。 图书馆被允许使用代码生成,虽然我相当确定没有它可以做到这一点。

注意我对数据可移植性不感兴趣。 我想用它作为caching,所以我可以依靠不变的环境。

谢谢。


结果

有人build议Tpl这是一个很棒的库,但我相信它不会做任意的对象图,比如每个包含两个节点的节点树。

另一位候选人是Eet ,这是启蒙窗口pipe理器的一个项目。 看起来很有趣,但似乎又没有序列化嵌套结构的能力。

看看tpl 。 从概述:

Tpl是用于序列化C数据的库。 数据以自然二进制forms存储。 该API很小,并试图保持“挡路”。 与使用XML相比,tpl在C程序中更快更容易使用。 Tpl可以序列化许多C数据types,包括结构。

我知道你在找图书馆 如果你找不到一个(:: boggle ::,你会认为这是一个解决的问题!),这里是一个解决scheme的大纲:

你应该能够编写一个代码生成器[1],无需(运行时)预处理就可以简单地序列化树/图。

你需要parsing节点结构( typedef处理?),并以直线的方式写入包含的数据值,但要小心处理指针。

  • 对于你知道被单引用的其他对象(比如char *name; )的指针,你可以直接序列化目标数据。

  • 对于可能被多重引用的对象和树的其他节点,您必须表示指针结构。 每个对象被分配一个序列号,这就是写在指针的地方。 保持当前内存位置和序列号之间的翻译结构。 在遇到一个指针时,看看它是否已经被分配了一个数字,如果没有,就给它一个,并将这个对象排队以便序列化。

回读还需要一个节点 – #/内存位置转换步骤,并且可能更容易在两遍中执行:使用指针槽中的节点号重新生成节点(错误指针,被警告)以找出每个节点获得的位置放,然后再走固定指针的结构。

我对tpl一无所知,但是你也许可以捎带回去。


磁盘/networking格式应该可能与一些types信息构成。 你将需要一个名称改造计划。


[1] ROOT使用这种机制在C ++中提供了非常灵活的序列化支持。


后期补充:对我来说,这并不总是像我上面所说的那么简单。 考虑以下(devise和devise不当)的声明:

 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

您将需要小心devise数据结构和/或为序列化过程带来一些特定情况的智能。

这是我的解决scheme。 它使用我自己的malloc,free和mmap,munmap系统调用的实现。 按照给出的示例代码。 参考: http : //amscata.blogspot.com/2013/02/serialize-your-memory.html

在我的方法中,我创build一个char数组作为我自己的RAM空间。 然后有分配内存和释放他们的function。 在创build数据结构之后,通过使用mmap ,我将char数组写入文件。

无论何时你想把它加载回内存,都有一个函数使用munmap把数据结构再次放到char数组中。 由于它具有指针的虚拟地址,因此可以重新使用您的数据结构。 这意味着,您可以创build数据结构,保存,加载,再次编辑,然后再保存。

你可以看看eet 。 启蒙项目的库,用于存储C数据types(包括嵌套结构)。 虽然几乎所有启蒙项目的库都处于pre-alpha状态,但是eet已经被释放了。 但是,我不确定它是否可以处理循环引用。 可能不会。

你应该检查gwlib。 串行器/解串器是广泛的。 并有广泛的testing可供查看。 http://gwlib.com/

我假设你正在谈论存储一个graphics结构,如果没有,然后无视…

如果你存储一个图,我个人认为最好的想法是实现一个函数,把你的图转换成一个邻接matrix。 然后可以创build一个将邻接matrix转换为graphics数据结构的函数。

这有三个好处(在你的应用程序可能或不重要):

  • 邻接matrix是创build和存储graphics的一种非常自然的方式
  • 您可以创build一个邻接matrix并将其导入到您的应用程序中
  • 您可以用有意义的方式存储和读取数据。

我在一个CS项目中使用了这个方法,当然我又会这样做。

你可以在这里阅读更多关于邻接matrix: http : //en.wikipedia.org/wiki/Modified_adjacency_matrix

另一种select是Avro C ,它是C中Apache Avro的实现。

理论上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); 

如果你不想使用string作为键,你可以使用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); 
    Interesting Posts