我想要一个可以将我的数据结构序列化到磁盘的C库,然后再加载它们。它应该接受任意嵌套的结构,可能还有循环引用。
我认为这个工具需要一个描述我的数据结构的配置文件。允许库使用代码生成,尽管我很确定没有它就可以这样做。
注意我对数据可移植性不感兴趣。我想将它用作缓存,所以我可以依赖不改变的环境。
感谢。
结果的
有人建议Tpl这是一个很棒的库,但我相信它不会做任意对象图,例如每个包含两个其他节点的节点树。
另一位候选人是Eet,这是Enlightenment窗口管理器的一个项目。看起来很有趣但是,似乎没有能力序列化嵌套结构。
答案 0 :(得分:16)
结帐tpl。从概述:
Tpl是一个用于序列化C的库 数据。数据存储在其中 自然二进制形式。 API很小 并试图保持“不在路上”。 与使用XML相比,tpl更快 并且更容易在C程序中使用。 TPL 可以序列化许多C数据类型, 包括结构。
答案 1 :(得分:10)
我知道你要的是一个图书馆。如果你找不到一个(:: boggle ::,你认为这是一个已经解决的问题!),这里有一个解决方案的大纲:
您应该能够编写代码生成器[1]来序列化树/图,而不需要(运行时)预处理。
您需要解析节点结构(typedef
处理?),并以直接的方式编写包含的数据值,但要小心处理指针。
对于单独引用您知道的其他对象(即char *name;
)的指针,您可以直接序列化目标数据。
对于可能被多次引用的对象以及树的其他节点,您必须表示指针结构。每个对象都被分配一个序列号,这是指针写入的内容。保持当前内存位置和序列号之间的转换结构。在遇到指针时,查看它是否已经分配了一个数字,如果没有,则给它一个并将该对象排队以进行序列化。
回读还需要一个节点 - #/内存位置转换步骤,并且在两次传递中可能更容易做到:用指针槽中的节点号重新生成节点(坏指针,被警告)以找出哪里每个节点都被放置,然后再次走结构修复指针。
我对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
?
您需要注意设计数据结构和/或为序列化过程带来一些特定于案例的智能。
答案 2 :(得分:6)
这是我的解决方案。它使用我自己的malloc,free和mmap,munmap系统调用的实现。按照给定的示例代码。参考:http://amscata.blogspot.com/2013/02/serialize-your-memory.html
在我的方法中,我创建一个char数组作为我自己的RAM空间。然后有分配内存和释放它们的功能。创建数据结构后,使用mmap
,我将char数组写入文件。
每当您想将其加载回内存时,都会有一个函数使用munmap
将数据结构再次放入char数组。由于它具有指针的虚拟地址,因此您可以重新使用数据结构。这意味着,您可以创建数据结构,保存,加载,再次编辑,然后再次保存。
答案 3 :(得分:4)
您可以查看eet。用于存储C数据类型(包括嵌套结构)的enlightenment项目库。虽然几乎所有启蒙项目的lib都处于pre-alpha状态,但eet已经被释放。但是,我不确定它是否可以处理循环引用。可能不是。
答案 4 :(得分:3)
答案 5 :(得分:3)
你应该结帐gwlib。串行器/解串器是广泛的。并且有广泛的测试可供查看。 http://gwlib.com/
答案 6 :(得分:2)
我假设您正在谈论存储图形结构,如果没有则忽略......
如果您存储图表,我个人认为最好的想法是实现一个将图形转换为邻接矩阵的函数。然后,您可以创建一个将邻接矩阵转换为图形数据结构的函数。
这有三个好处(在您的申请中可能或可能不重要):
我在CS项目中使用过这种方法,我肯定会再次这样做。
您可以在此处详细了解邻接矩阵:http://en.wikipedia.org/wiki/Modified_adjacency_matrix
答案 7 :(得分:1)
另一个选项是Avro C,是C中Apache Avro的实现。
答案 8 :(得分:1)
以下是使用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);
答案 9 :(得分:0)
理论上,YAML应该做你想做的事http://code.google.com/p/yaml-cpp/
如果它适合您,请告诉我。