我想要一个可以将我的数据结构序列化到磁盘的C库,然后再加载它们.它应该接受任意嵌套的结构,可能使用循环引用.
我认为这个工具需要一个描述我的数据结构的配置文件.允许库使用代码生成,尽管我很确定没有它就可以这样做.
注意我对数据可移植性不感兴趣.我想将它用作缓存,所以我可以依赖不改变的环境.
谢谢.
结果
有人建议Tpl是一个很棒的库,但我相信它不会做任意的对象图,例如每个包含两个其他节点的节点树.
另一个候选人是Eet,这是Enlightenment窗口管理器的一个项目.看起来很有趣但是,似乎没有能力序列化嵌套结构.
看看tpl.从概述:
Tpl是一个用于序列化C数据的库.数据以其自然二进制形式存储.API很小,并试图保持"不碍事".与使用XML相比,tpl在C程序中使用更快,更容易.Tpl可以序列化许多C数据类型,包括结构.
我知道你要的是一个图书馆.如果你找不到一个(:: 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
?
您需要注意设计数据结构和/或为序列化过程带来一些特定于案例的智能.
这是我的解决方案.它使用我自己的malloc,free和mmap,munmap系统调用的实现.按照给定的示例代码.参考:http://amscata.blogspot.com/2013/02/serialize-your-memory.html
在我的方法中,我创建一个char数组作为我自己的RAM空间.然后有分配内存和释放它们的功能.创建数据结构后,通过使用mmap
,我将char数组写入文件.
每当你想将它加载回内存时,就会有一个函数用于munmap
将数据结构再次放入char数组.由于它具有指针的虚拟地址,因此您可以重新使用数据结构.这意味着,您可以创建数据结构,保存,加载,再次编辑,然后再次保存.