ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 概述 在最新的skynet中我使用的是云风的pbc库来解析protobuf,该项目中的一个文件protobuf.lua 使用了module语法在lua5.1版本中已经删除,最新的skynet是lua5.4版本,于是我找到了解析protobuf的lua库--lua-protobuf。在最新的skynet中,集成lua-protobuf 所需环境如下: * skynet * lua5.4 * luarocks * lua-protobuf : https://github.com/starwing/lua-protobuf * ubuntu16.04 ## Install skynet & luarocks & lua-protobuf 编译安装`skynet` ```shell $ git clone https://github.com.cnpmjs.org/cloudwu/skynet.git $ cd skynet && make linux ``` 编译安装`luarocks` ```shell $ wget https://luarocks.github.io/luarocks/releases/luarocks-3.5.0.tar.gz $ tar -zxvf luarocks-3.5.0.tar.gz $ cd luarocks-3.5.0 $ ./configure --prefix=/usr/local/luarocks --with-lua-bin=/aseit-data/work_zhang/cppCode/lastBattle_skynet/skynet/3rd/lua --with-lua-include=/aseit-data/work_zhang/cppCode/lastBattle_skynet/skynet/3rd/lua ``` >`--prefix` 设置 `Luarocks` 安装路径,`--with-lua-bin` 指定`Luarocks`依赖的 Lua 路径。`--with-lua-bin`和`--with-lua-include`这两个参数指定的是skynet项目中所使用的lua5.4库路径。 编译安装`lua-protobuf` ```shell $ git clone https://github.com.cnpmjs.org/starwing/lua-protobuf.git && cd lua-protobuf $ luarocks make rockspecs/lua-protobuf-scm-1.rockspec ``` ## 在skynet中使用lua-protobuf `lua-protobuf`编译成功的话,将`pb.so`放在config文件中`lua_cpath`项配置的目录下面,同时将`protoc.lua`放在config文件`lua_path`配置的目录下,就可以调用`protoc`中的库方法。我当前项目这两项的配置如下: ```lua lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua" lua_cpath = root .. "luaclib/?.so" ``` 官方的例子是直接使用protoc加载一个protobuf。我们一般使用protobuf是先写`.proto`文件,然后用`protoc`命令生成`.pb`文件,然后在项目中使用 `.pb`文件 示例`GCToLS.proto`: ```proto syntax = "proto3"; package GCToLS; enum MsgID { eMsgToLSFromGC_Begin1 = 0; eMsgToLSFromGC_Begin = 1; eMsgToLSFromGC_AskLogin = 2; eMsgToLSFromGC_End = 3; } message AskLogin { MsgID msgid = 1; uint32 platform = 2; string uin = 3; string Sessionid = 4; } ``` 使用`protoc`命令编译成`.pb`文件 ```shell sudo protoc --descriptor_set_out ./pbs/gctols.pb ./ProtoFile/GCToLS.proto ``` >语法格式 protoc --descriptor_set_out 输出 输入 ## 在skynet项目中使用`lua-protobuf`. 1.载入gctols.pb文件 ```lua local pb = require "pb" assert(pb.loadfile "./protos/pbs/gctols.pb") ``` 2.获取enum类型 ```lua pb.enum("GCToLS.MsgID", "eMsgToLSFromGC_AskLogin") ``` 3.编解码数据 ```lua function gctols.encode(asklogin) return assert(pb.encode("GCToLS.AskLogin", asklogin)) end function gctols.decode(asklogin) return assert(pb.decode("GCToLS.AskLogin",asklogin)) end ``` 完整示例: ```lua //gctols.lua local pb = require "pb" assert(pb.loadfile "./protos/pbs/gctols.pb") -- 载入刚才编译的pb文件 local gctols = {} function gctols.msgid() return pb.enum("GCToLS.MsgID", "eMsgToLSFromGC_AskLogin") end function gctols.type(type) return pb.enum("GCToLS.MsgID", type) end function gctols.encode(asklogin) return assert(pb.encode("GCToLS.AskLogin", asklogin)) end function gctols.decode(asklogin) return assert(pb.decode("GCToLS.AskLogin",asklogin)) end return gctols ``` test.lua ``` local gctols = require "gctols" local asklogin = { msgid = "eMsgToLSFromGC_AskLogin", platform = 1, uin = "1", Sessionid = "1" } local encodedata = gctols.encode(asklogin) local decodedata = gctols.decode(encodedata) ``` 这里要注意的是,`.proto`文件中成员变量区分大小写,在解码得到的`table`数据,在获取对应的key数据时需要大小写对应。在编码`table`数据时,对应的`key`也要大小对应,不然编码不通过。比如上面的`Sessionid`这个`key`。 使用lua-protobuf的细节请参考官方[github](https://github.com/starwing/lua-protobuf):