自定义脚本引擎开发纪实 - struct的pack和unpack(注意与python的不同)
程序员文章站
2022-04-10 15:35:59
...
在处理网络数据时,比如tcp包字节流的时候,需要pack/unpack。
这里采用的方式和python不同。
设计的初衷是:在C/C++中对元素的访问和在脚本中保持一致。
比如:
c/c++代码
//c/c++访问方式
struct user
{
char name[10];
int id;
};
user usr = {"yew", 1};
char* name = usr.name;
int id = usr.id;
期望在脚本中也是这样访问,比如:
name=usr.name
id=usr.id
实际例子
以下面这个稍微复杂的结构体为例:
struct tagInfo
{
char name[5][11];
struct
{
int l;
int h;
char s_name[7];
}s[2];
int id[2][3];
};
加上,从网络上接收到的数据buffer是一个这样的结构体,下面演示脚本如何解析。
根据C/C++定义的结构体,构造与之对应的脚本结构体format。
//定义一个结构体对象
st = struct()
//生成一个结构体format(一个c/c++中的struct对应一个structtype)
f=st.structtype()
//指定类型
f.name="char[5][11]"
//嵌套的struct
struct_s = st.structtype()
struct_s.l="i4"
struct_s.h = "i4"
struct_s.s_name = "char[7]"
//定义一个数组(没有python方便)
f.s = []
//结构体的数目为2,每个元素是一个struct_s结构体format
f.s.setcount(2, struct_s)
f.id="i4[2][3]"
//设置对象的format为上述构造的format
st.format(f)
calcsize方法
我们调用一下calcsize方法,获取一下上述结构体的大小。有一个参数,是字节对齐的方式,可以取1,2,4,8。
//4字节对齐
len=st.calcsize(4)
calc_offset_len方法
calc_offset_len方法也是只有一个参数,字节对齐的方式,可以取1,2,4,8。作用是获取每一个元素的大小和在结构体中的偏移。
sz = st.calc_offset_len(4)
//打印id字段的偏移和占用的总长度
os.debug.log("offset\t" + sz.id._offset + "\tlen\t" + sz.id._len)
unpack方法
unpack方法有两个参数:1是字节流(stream)2是字节对齐方式。作用是解析字节流。
//从网络上接受的结构体buffer
stream = os.net.get("https://xxx.xx.xxx/interface")
info=st.unpack(stream, 4)
//打印info.name[1][0]
os.debug.log(info.name[1][0])
pack方法
有两个参数:第一个是:含有数据的key-value对。第二个参数是字节对齐方式。
作用是:生成字节流。
//修复info的数据
info.id[0][0]=100
//生成字节流
stream_pack=st.pack(info, 4)
c/c++中通过[].对元素的访问,在脚本中保持了一致。
上一篇:
体检套餐管理系统 -- List