对象序列化是做什么的,作为了一个常用C语言写代码的嵌入式工程师,最开始确实有些难以理解。直到遇到一些项目,才体会到对象序列化和反序列化的用处。
对于C语言来说,结构体就可以定义对象,这种对象的数据就在内存中,已经序列化,想要将其传输,只需要对象的地址和长度即可。而接收端,只要有这个结构体的定义,很容易就可以将传输的内容,反序列化,最终得到传输的结构体对象的内容。但是,仅仅对于两端都是c语言实现的程序,就存在两个问题:结构体的对齐和数据大小端问题。对于这两条规则,序列化和反序列化两端,结构体的对齐规则和大小端必须一致,否则,反序列化就会出问题。相同语言尚且如此,跨语言呢,c语言结构体对象序列化的数据,用python 来反序列化呢,python可没有结构体,没有指针,怎么反序列化?这里我们就要借助第三方工具了,比如protobuf,借助它我们就可以实现跨平台(8bit/16bit/32bit mcu, 32bit/64bit cpu, windows /linux),跨语言(c语言/c++/java/go/python等),实现对象的序列化和反序列化。比如在32bit的单片上,我们借助protobuf 用C语言将一个结构体对象序列化,通过以太网传输到windows电脑上;电脑端通过python程序接收来自以太网的数据,并将其反序列化从而获取传输的对象。由于对象序列化过程中,会对对象属性数据重新编码,在某种意义上还起到了一定程度的信息加密作用。
话不多说,例子举来。
例子的主要流程见上图。
- 我定义了一个对象player,有身高,体重,坐标x、y、z等属性,并且根据protobuf的规则将对象定义在player.proto文件中。
- 执行命令.\protoc.exe --nanopb_out=. player.proto,生成了C语言版本的对象定义文件player.pb.h 和player.pb.c。
- 执行命令.\protoc.exe --python_out=. player.proto,生成python版本的对象定义文件player_pb2.py。
- C程序中,集成protobuf 协议栈和对象定义文件,定义对象player,对对象赋值,序列化对象,生成序列化内容——一串神秘数字。
- python程序中,集成protobuf 协议栈和对象定义文件,将C语言程序生成的那串神秘数字进行反序列化,得到对象player各个属性的值。
Note:
- 官方protobuf工具不支持C语言,这里采用的是非官方支持protobuf协议的实现工具nanopb,下载可见附件nanopb-0.4.6-windows-x86.zip
- protoc.exe 见附件路径 .\nanopb-0.4.6-windows-x86\generator-bin,通过不同命令参数--xxx_out= 可以生成对应语言的对象定义程序文件。
- nanopb 附件中包含了C语言的protobuf 协议栈,需要手动集成到C语言工程中去,见附件c语言序列化编码附件c_encode_src。
- python 工程可以通过import 直接引用protobfuf的协议栈,python 反序列化解码见附件python_decode.