欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自定义脚本引擎开发纪实 - 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++中通过[].对元素的访问,在脚本中保持了一致。