- 论坛徽章:
- 8
|
我做过。
需求是:
1、将预定义的c结构体写成固定格式的xml字符流,或从xml字符流中恢复此c结构体。
2、此类操作逻辑相对固定,能否写成通用函数?
思路:
1、使用offsetof宏求得c结构体中每个字段相对于指向该结构体的指针的偏移。
例:
struct aa
{
int I1; //offsetof(aa,I1) = 0
int I2; //offsetof(aa,I2) = 4
}
若 aa * point = &x, 则 *(int *)((void *) point + offsetof(aa,I1))就相当于point->I1
2、生成一个全局对应表,记录struct名、成员变量偏移、成员变量数据类型以及它们对应的字符串名称(如"aa"、"I1"、"I2"等)
我当时定义了一组宏,很简单就可完成这个工作。
3、没啥了。查表、转换而已(如 输入“aa->I1 = 2”或"<aa><I1>2</I1></aa>",就将其转换为 aa a1; *(int *)((void*)&a1 + offsetof(aa,I1)) = 2)。
这里也可以定义成宏。
注意: 这是我当时在c中实现的方法,非常丑陋;c++中提供有更好的方法(请 google 搜索 指向成员变量的指针 的相关内容)。
由于当初实现时没有相关经验,甚至其中的offsetof宏也是我自己杜撰的;后来与c++代码混编时被编译器提示用成员变量指针代替offsetof宏,才知道自己又重新发明了轮子。
不过,用c++实现的话,最好的办法还是采用“序列化”模式(参考c++流设计思路;不过它是“流”向普通文件,我是“流”向xml格式缓冲区而已);所以也懒得重构这个东东了,干脆用类似机制重新写了个通用的“可序列化到xml”基类。
另外,微软新近推出的WPF,从它的核心技术之一“依赖属性(DependencyProperty)”的声明、使用方式看,其内部实现显然也采用了类似的思路。
PS:
指向成员变量的指针语法如下:int aa::*ptr = &aa::I1
以后,若有aa x1;则 *(x1.ptr)就相当于x1.I1
这个办法可以避免传入的结构体类型不匹配导致程序崩溃(俺当初是干脆引入模板参数推导机制,搞了个c+泛型的BT东东-_-|||;这个丑陋实现也是后来重写时改用 可序列化到xml 类机制的原因之一)。
这是offsetof宏的定义:
#define offsetof(structName,item) (size_t)&(((structName *)0)->item)
原理: 强制转换0为structName *;则 &(((structName *)0)->item)就是item相对于结构体首字节的偏移量;为避免指针相加警告,因而又将其强制转换为size_t。 |
|