首先我們需要的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
import "basic.proto";
message Sell{
optional int32 t = 1;
repeated protobuf_basic_export.Item items = 2;
...
}
這樣導出不會報錯了,符合protobuf的書寫要求。
但是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關係