2001年的时候,在我的第一个正经项目里,我遇到一个问题:我们的程序是客户端,通过socket和服务端通信,用的二进制协议。二进制协议真是太痛苦了,为了查一个错误,常常要用sniffer把包拦截了,然后一个byte一个byte的比较,因为byte order的关系,还得倒过来看。当时我的同事想写一个工具,能够把二进制的协议显示成一棵树,因为这些数据本来就是C Structure的内存的反映。不过他只能在业余时间做,到最后项目基本结束,我离开公司,这个工具也没有完成。正好论坛里也有人问类似的问题:struct mydata{ int a; int b;};struct msg{ int i; struct mydata data;};希望能得到如下输出:msg: i = 100 data: a = 1 b = 2我猜可能也是类似的用途。这个问题在2004年我开始在现在的公司设计通讯协议的时候再次出现,不过有了一个新名字:XML 数据绑定。也就是要把C 的struct data转换为XML。当时我们选用了商业商品XBinder。这个工具的工作原理在vckbase blog的某位博主的帖子里有介绍,我再重复一下:首先编写XML Schema,定义消息格式,类似于C struct,不过可以加上非常复杂的约束,比如要求a > 10 && a < 100XBinder 提供一个工具,读入这个Schema 文件,而输出的则是一些C/C++的源代码,这些源代码提供类似下面的函数:xmlstring* Encode_msg(struct msg)struct msg* Decode_msg(xmlstring*)这样,就可以很容易的实现C Struct 和 XML 文档之间的转换。这个过程的术语叫:XML 数据绑定后来,我们又希望这些C Struct 可以和二进制流互相转换,这个XBinder做不了,不过有人能做。有一种标准叫ANS.1,就是二进制的,围绕它有好多类似XBinder的工具。不过我们可不希望同时使用这两种完全没法兼容的工具,所以,就决定自己做了。(如果没有byte order问题,会简单一些,可以直接memcpy.不过我们有这个问题,而且还希望支持动态数组等分配在堆上的内存)思路其实很简单,分两步:1.分析输入文件:我们的输入文件就是C Header File脚本程序将文件读入,然后分析出其中所有的enum,struct,union等等,也包括他们的成员的类型,名字等信息。这个过程完全可以手写代码完成,用不着上bison,flex. 我们对输入的Header File 格式作了一些限制,比如不允许用/**/注释,不允许在一行里写多句,这样分析起来就更加简单,基本上一行行的读入,再弄个简单的状态机就可以了。而且在分析之前,用VC6的编译器先编译一次,没有问题才开始,所以也省略了错误检查的工作,而认为所有的输入文件都是符合C规范的。2. 产生C++代码:有了第一步得到的信息,产生C++代码也就不难了,比如针对struct mydata{ int a; int b;};可以产生这样的代码:
因为是公司的产品,我不能讲的更多。不过我想这个思路就是这么回事。同理,我们可以产生各种各样的输出,csv,xml,也包括论坛上的朋友希望要的东西。
posted on 2006-07-11 18:30 jzhang 阅读(597) 评论(0) 编辑 收藏
Powered by: Copyright © jzhang