具有网络功能的嵌入式产品的控制一般是通过发送命令完成的,命令对应的值一般分为单值命令和结构体块数据两类。举例如下:
/*define two commands*/ #define CMDA 0x0f #define CMDB 0x0e /*define a value*/ int a = 0; /*define a struct*/ struct B{ int b; int c; char d[4]; }b; /*send CMDA with a single value*/ send(CMDA, &a, sizeof(int)); /*sendCMDB with struct data*/ send(CMDB, &b, sizeof(struct B));
如果我们要设计一个网页控制系统,需要满足以下需求:
需求1:网页上的控件与设备里面的参数一一对应,无论是单值还是结构体中的成员;
具体情况如下:
/* 假设网页上有一个输入框,它绑定一个命令号,如果该命令号是单值,直接绑定该值; 如果该命令号是个结构体,我们需要寻求一种方法将结构体成员与该网页控件对应,更改该控件的值就可以直接反应到结构体的成员中。 */
在这里,我把我设计的解决方案分享一下。
首先,指定结构体中的成员变量,我采用了类似Xpath的概念,此处我就把它简称为Spath(Struct member path),与Xpath相区别。
扫描二维码关注公众号,回复:
496243 查看本文章
那么Spath是怎么样指定结构体中的成员的呢?
以前面结构体B为例,Spath举例如下:
/*represent member b*/ /B/b /*represent member c*/ /B/c /*represent member d*/ /B/d
以/开始紧跟结构体名,直到最终成员结束。
此时,我们可以用cmd和Spath区别开不同的结构体成员了,如果我们将cmd和Spath提交给CGI程序处理,/B/c这个Spath指定了结构体的第二个成员变量,那么我们可以更新或者读取B结构体二进制数据中的对应的值。但是,这一过程是人工去判断的,具体说是CGI编程人员去判断的,那么这个工作量是相当大的,而且如果结构体变化,CGI也会修改并重新编译。一点都不灵活。
为了优化这个过程,使全程自动化,我引入了动态结构体的概念。
什么是动态结构体?
/* 简单点说,动态结构体的成员是在运行时确定的,不是在编译时确定的。我们都知道C/C++结构体都是声明后在编译时内存大小和成员位置就已经确定好了,我们不能在运行时去动态的为结构体添加一个成员,当然开辟一块新内存去操作也是可以做到的,这个办法不在此次讨论之内。我这里说的动态结构体就是可以在运行时增删改查结构体成员。 */
动态结构体的原理是什么?
/*动态结构体的核心是一个hash表,将结构体的成员名字,类型定义到一个配置文件中,我选择的是json格式。 { “B”:[ {"name":"b","type":"int"}, {"name":"c","type":"int"}, {"name":"d","type":"array","subtype":"char","length":4} ] } 注意:这里结构体定义需要按照成员的顺序定义 运行时,程序读取配置,将配置信息存在hash表中,生成结构体,这时解析Spath就可以找到对应成员在结构体中的位置。即使结构体更改,也不用重新编译程序,更改结构体配置文件就可以。 */