首先我们需要的protobuf导出lua的工具https://github.com/sean-lin/protoc-gen-lua, 具体使用,编写自己的proto文件,使用protoc --lua_out=./ foo.proto 导出lua文件即可,导出lua文件的主要实现是在plugin下的protoc-gen-lua文件。本身此工具不支持proto的嵌套,比如有两个proto文件
basic.proto里包换一个message:
message Item{
required int32 id = 1;
...
}
而另一个proto引用basic.proto的Item这个message,比如user_proc.proto
message Sell{
optional int32 t = 1;
repeated Item items = 2;
...
}
如果不加任何引用的话,上述proto会报错的,正常情况下,需要引进package,针对basic.proto和user_proc.proto做如下修改:
#basic.lua
package protobuf_basic_export
.....
#user_proc.proto这样导出不会报错了,符合protobuf的书写要求。
import "basic.proto";
message Sell{
optional int32 t = 1;
repeated protobuf_basic_export.Item items = 2;
...
}
但是protoc-gen-lua导出的lua文件就有些问题,执行后发现,user_proc_pb_lua会报错:BAISC_PB_ITEM找不到,这个是工具产生的字段,当该type不在当前proto下时会产生,是合成的字段,lua执行的话肯定找不到这个字段,我们要修改的也是这个地方要改成如下:
USER_PROC_ITEM_FIELD.message_type = BASIC_PB.ITEM
而BASIC_PB要指向导出的basic_pb.lua文件,所以修改导出的python文件,实现我们的要求:
1:去除合并
if field_desc.HasField('type_name'):
type_name = env.get_ref_name(field_desc.type_name).upper()
:2:message descriptor设为全局,
def code_gen_message(message_descriptor, env, containing_type = None):
env.enter(message_descriptor.name)
full_name = env.get_local_name()
obj_name = full_name.upper().replace('.', '_')
env.descriptor.append(
"%s = protobuf.Descriptor();\n"% obj_name
):
3:引用pb大写, 与类型一致 即local BASIC_PB = require("basic_pb")
if is_gen:
lua = Writer()
write_header(lua)
lua('local protobuf = require "protobuf"\n')
for i in includes:
lua('local %s_PB = require("%s_pb")\n' % (i.upper(), i))
lua("module('%s_pb')\n" % env.filename)
导出后文件变成:
-- Generated By protoc-gen-lua Do not Edit
local protobuf = require "protobuf"
module('basic_pb')
ITEM= protobuf.Descriptor();
local ITEM_ID_FIELD = protobuf.FieldDescriptor();
-- Generated By protoc-gen-lua Do not Edit
local protobuf = require "protobuf"
local BASIC_PB = require("basic_pb")
module('user_proc_pb')
SELL_ITEMS_FIELD.message_type = BASIC_PB.ITEM
这样BASIC_PB.ITEM是可以找到的,就在basic_pb.lua里
git https://github.com/AdamWu/protoc-gen-lua
ps:你可以使用云风的pb,它支持嵌套proto关系