概述

在最新的skynet中我使用的是云风的pbc库来解析protobuf,该项目中的一个文件protobuf.lua 使用了module语法在lua5.1版本中已经删除,最新的skynet是lua5.4版本,于是我找到了解析protobuf的lua库–lua-protobuf。在最新的skynet中,集成lua-protobuf

所需环境如下:

Install skynet & luarocks & lua-protobuf

编译安装skynet

$ git clone https://github.com.cnpmjs.org/cloudwu/skynet.git 
$ cd skynet && make linux

编译安装luarocks

$ 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

$ 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_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua"
lua_cpath = root .. "luaclib/?.so"

官方的例子是直接使用protoc加载一个protobuf。我们一般使用protobuf是先写.proto文件,然后用protoc命令生成.pb文件,然后在项目中使用 .pb文件
示例GCToLS.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文件

sudo protoc --descriptor_set_out ./pbs/gctols.pb ./ProtoFile/GCToLS.proto

语法格式 protoc –descriptor_set_out 输出 输入

在skynet项目中使用lua-protobuf.

1.载入gctols.pb文件

local pb = require "pb"
assert(pb.loadfile "./protos/pbs/gctols.pb")

2.获取enum类型

pb.enum("GCToLS.MsgID", "eMsgToLSFromGC_AskLogin")

3.编解码数据

function gctols.encode(asklogin)
    return assert(pb.encode("GCToLS.AskLogin", asklogin))
end
function gctols.decode(asklogin)
    return assert(pb.decode("GCToLS.AskLogin",asklogin))
end

完整示例:

//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:

--完--