Protobuf 核心库:高效序列化,让设备通信更快更轻量
Protocol BuffersProtobuf是 Google 推出的跨语言、跨平台、轻量高效的数据序列化协议具备体积小、解析快、扩展性强、兼容性好等优势广泛用于网络通信、数据存储、协议交互等场景。LuatOS 对底层 Protobuf 编解码进行深度优化与极简封装无需复杂配置只需调用少量 API即可快速实现数据编码、数据解码、协议解析等核心能力大幅降低协议对接成本提升通信效率与代码可维护性。目前Protobuf库已全面支持LuatOS开发系列产品开发者可根据项目实际需求灵活选用并进行快速集成与开发。一、Protobuf核心库速览LuatOS的Protobuf核心库支持加载由protoc编译生成的二进制描述文件.pb提供完整的数据编码encode、数据解码decode等功能支持Proto2和Proto3协议版本能够根据输入的protobuf定义自动识别并处理相应版本的消息格式适用于设备与云端、模块间高效数据交换等典型应用场景。最新API文档详见https://docs.openluat.com/osapi/core/protobuf/在LuatOS开发中使用以下四个函数高效处理Protobuf数据。1.1 protobuf.load(pbdata)函数功能加载Protocol Buffers二进制定义数据到系统中使其可以用于后续的编码和解码操作。注意事项同一个文件只需要加载一次除非调用过 protobuf.clear() 清除已加载的定义加载的数据必须是通过protoc.exe程序转换得到的二进制数据。简要示例-- 加载 pb 文件, 这个是 proto 经过 protoc.exe 编译后生成的二进制文件-- 下载资源到模块时不需要下载 proto 文件-- 转换命令: protoc -o person.pb person.proto-- protoc.exe 下载地址: https://github.com/protocolbuffers/protobuf/releaseslocalpb_file/luadb/person.pbifio.exists(pb_file)thenlocalsuccess,bytesReadprotobuf.load(io.readFile(pb_file))ifnotsuccessthenlog.info(protobuf,加载 protobuf 定义失败已读取 ..bytesRead.. 字节)returnelselog.info(protobuf,加载 protobuf 定义成功共解析 ..bytesRead.. 字节)endelselog.info(protobuf,pb 文件不存在)returnend1.2 protobuf.clear()函数功能清除已加载的Protocol Buffers二进制定义数据。注意事项清除所有定义数据后可以通过调用protobuf.load()重新加载新的定义数据清除后任何依赖已删除类型的序列化/反序列化操作将失败该函数总是成功执行没有返回错误的情况。简要示例-- 清除所有已加载的定义数据protobuf.clear()log.info(protobuf,所有 protobuf 定义已清除)end1.3 protobuf.encode(tpname, data)函数功能将符合Protocol Buffer消息定义的Lua表table数据按照指定的消息类型进行序列化生成二进制编码后的字符串。注意事项编码前必须先使用protobuf.load()加载对应的Protocol Buffer定义数据待编码的table内容必须符合pb文件里的定义编码结果为二进制字符串可能包含不可打印字符调试时建议使用十六进制如 :toHex()或Base64查看如果编码失败函数会返回nil。简要示例-- 准备待编码数据localpb_file/luadb/person.pblocaltbdata{namewendal,id123,emailabcqq.com}-- 编码数据localpbdataprotobuf.encode(Person,tbdata)ifpbdatathen-- 编码成功编码后的数据通常包含不可见字符-- 打印长度和十六进制内容便于调试log.info(protobuf,编码成功数据长度..#pbdata)log.info(protobuf,十六进制内容..pbdata:toHex())elselog.info(protobuf,编码失败数据格式或类型不匹配)end1.4 protobuf.decode(tpname, data)函数功能将Protocol Buffer二进制编码的数据字符串按照指定的消息类型进行反序列化还原为Lua表table结构。注意事项在调用此接口前必须先通过protobuf.load()加载对应的Protocol Buffers定义数据输入数据data必须是有效的protobuf二进制编码字符串且与tpname对应的消息格式兼容Lua table内容无法直接打印出来建议搭配json.encode()查看。简要示例--假设已通过 protobuf.load()加载了 Person 类型定义;--例如通过 protobuf.encode() 生成的返回值变量为 pbdata;-- 数据解码localtbdataprotobuf.decode(Person,pbdata)iftbdatathen-- 解码后的数据为 Lua table 格式需要转化为 json 进行显示log.info(protobuf,解码成功数据内容,json.encode(tbdata))elselog.info(protobuf,解码失败)end二、开源示例快速上手理论结合实践才能更快掌握。完整Protobuf示例已开源在合宙LuatOS官方仓库你可以直接参考并使用。以合宙低功耗模组Air780EHV音频全能系列为例可选用配套核心板或开发板快速实操验证。最新示例源码https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM_Air780EHV_Air780EGH/demo/protobuf实操教程详见https://docs.openluat.com/air780ehv/luatos/app/common/protobuf/Protobuf示例功能要点加载protobuf定义文件将符合protobuf定义的Lua table数据编码为二进制数据使用json编码同样的Lua table数据后对比protobuf和json编码后数据的大小将二进制数据解码为Lua table数据清除所有已加载的定义数据。核心代码如下图示完整demo详见源码仓库最新文件。--[[ 本功能模块演示的内容为 1.加载 protobuf 定义文件 2.将符合 protobuf 定义的 Lua table 数据编码为二进制数据 3.使用 json 编码同样的 Lua table 数据后对比 protobuf 和 json 编码后数据的大小 4.将二进制数据解码为 Lua table 数据 5.清除所有已加载的定义数据 本文件没有对外接口,直接在 main.lua 中 require protobuf_app 就可以加载运行 ]]localfunctionmain_task()-- 加载 pb 文件, 这个是 proto 经过 protoc.exe 编译后生成的二进制文件-- 下载资源到模块时不需要下载 proto 文件-- 转换命令: protoc -o person.pb person.proto-- protoc.exe 下载地址: https://github.com/protocolbuffers/protobuf/releaseslocalpb_file/luadb/person.pblocaltbdata{namewendal,id123,emailabcqq.com}ifio.exists(pb_file)thenlocalsuccess,bytesReadprotobuf.load(io.readFile(pb_file))ifnotsuccessthenlog.info(protobuf,加载 protobuf 定义失败已读取 ..bytesRead.. 字节)returnelselog.info(protobuf,加载 protobuf 定义成功共解析 ..bytesRead.. 字节)endelselog.info(protobuf,pb 文件不存在)returnend-- 编码数据localpbdataprotobuf.encode(Person,tbdata)ifpbdatathen-- 编码成功编码后的数据通常包含不可见字符-- 打印长度和十六进制内容便于调试log.info(protobuf,编码成功数据长度..#pbdata)log.info(protobuf,十六进制内容..pbdata:toHex())elselog.info(protobuf,编码失败数据格式或类型不匹配)end-- 对比 protobuf 编码和 json 编码的大小localjdatajson.encode(tbdata)ifjdatathenlog.info(json,编码成功数据长度..#jdata)log.info(json,数据内容..jdata)elselog.info(json,编码失败数据格式或类型不匹配)end-- 可见 protobuffs 比 json 节省很多空间-- 数据解码localtbdataprotobuf.decode(Person,pbdata)iftbdatathen-- 解码后的数据为 Lua table 格式需要转化为 json 进行显示log.info(protobuf,解码成功数据内容,json.encode(tbdata))elselog.info(protobuf,解码失败)end-- 清除所有已加载的定义数据protobuf.clear()log.info(protobuf,所有 protobuf 定义已清除)end-- 创建并启动一个 task-- 用于运行 main_task 函数sys.taskInit(main_task)