protoc-gen-lua 多嵌套引用修改

2020-06-08  本文已影响0人  nameLogen

protobuf 使我们经常使用的通信数据传输格式,为了方便lua直接使用proto 生成的文件,使用了protoc-gen-lua 工具,但是这个使用嵌套的proto 文件时,protoc.exe 无法正常引用,报错找不到对应的文件。所以后来参考下面两篇文章,修改了 protoc-gen-lua 这个Python文件,得到了想要的结果。废话不多说,直接上图:

目标文件

proto 文件夹结构
option java_package = "com.road.ddt.pb.game.login";
option java_outer_classname = "LoginMsgProto";
import "com/net/TestInfo.proto";

/* 登陆请求 code:8002*/
message LoginMsg {
    optional string userName = 1;
    optional string unixTime = 2;
    optional string signKey = 3;
    optional string host = 4;
    optional int32 port = 5;
    optional int32 userId = 6;
    optional int32 loginCode = 7;
    repeated TestInfoProto reslut = 8;
}
option java_package = "com.road.ddt.pb.com.net";
option java_outer_classname = "TestMsg";

message TestInfoProto {
    optional bool bool = 1;
    optional int32 int = 2;
}
option java_package = "com.road.ddt.pb.client.login";
option java_outer_classname = "LoginOutMsgProto";

import "com/net/TestInfo.proto";

/* 登陆结果返回 code:2*/
message LoginOutMsg {
    repeated TestInfoProto reslut = 1;
}

修改 protoc-gen-lua

修改 code_gen_field 方法


    if field_desc.HasField('type_name'):
        # type_name = env.get_ref_name(field_desc.type_name).upper().replace('.', '_')
        if field_desc.type == FDP.TYPE_MESSAGE:
            # 修改 引用其他文件夹下的message 时,把左边的文件名截取出来,再把右边的字段名大写处理 如: TestInfo_pb.TESTINFOPROTO
            typeNameL = env.get_ref_name(field_desc.type_name).split(".")[0]
            typeNameR = env.get_ref_name(field_desc.type_name).split(".")[1]

            typeNameLL = typeNameL.split("/")
            typeNameL = typeNameLL[len(typeNameLL) - 1]
            type_name = typeNameL +"."+ (typeNameR.upper())
            context('.message_type = %s\n' % type_name)
        else:
            type_name = env.get_ref_name(field_desc.type_name).upper().replace('.', '_')
            context('.enum_type = %s\n' % type_name)

修改 code_gen_message 方法


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('.', '_')
    # 修改 把local 去掉了,方便 TestInfo_pb.TESTINFOPROTO 能否直接访问到
    env.descriptor.append(
        "%s = protobuf.Descriptor();\n"% obj_name
    )
    # "local %s = protobuf.Descriptor();\n"% obj_name

修改 code_gen_file 方法


    if is_gen:
        lua = Writer()
        write_header(lua)
        lua('local protobuf = require "protobuf"\n')
        for i in includes:
            # 修改 将前面的local xx_pb 去掉 了,因为 这个require 返回的是 一个 true or false 
            lua('require("%s_pb")\n' % (i))
            # lua('local %s_pb = require("%s_pb")\n' % (i, i))
        # 修改 修改文件名,将文件名中的路径去掉
        typeNameLL = env.filename.split("/")
        typeNameL = typeNameLL[len(typeNameLL) - 1]
        # 修改 增加了",package.seeall" 多传入一个package.seeall的参数,相当于 setmetatable(M, {__index = _G}) .
        lua("module('%s_pb',package.seeall)\n" % typeNameL)

生成结果,保留了目录结构

image.png

LoginOutMsg_pb.lua

-- Generated By protoc-gen-lua Do not Edit
local protobuf = require "protobuf"
require("com/net/TestInfo_pb")
module('LoginOutMsg_pb',package.seeall)


LOGINOUTMSG = protobuf.Descriptor();
local LOGINOUTMSG_RESLUT_FIELD = protobuf.FieldDescriptor();

LOGINOUTMSG_RESLUT_FIELD.name = "reslut"
LOGINOUTMSG_RESLUT_FIELD.full_name = ".LoginOutMsg.reslut"
LOGINOUTMSG_RESLUT_FIELD.number = 1
LOGINOUTMSG_RESLUT_FIELD.index = 0
LOGINOUTMSG_RESLUT_FIELD.label = 3
LOGINOUTMSG_RESLUT_FIELD.has_default_value = false
LOGINOUTMSG_RESLUT_FIELD.default_value = {}
LOGINOUTMSG_RESLUT_FIELD.message_type = TestInfo_pb.TESTINFOPROTO
LOGINOUTMSG_RESLUT_FIELD.type = 11
LOGINOUTMSG_RESLUT_FIELD.cpp_type = 10

LOGINOUTMSG.name = "LoginOutMsg"
LOGINOUTMSG.full_name = ".LoginOutMsg"
LOGINOUTMSG.nested_types = {}
LOGINOUTMSG.enum_types = {}
LOGINOUTMSG.fields = {LOGINOUTMSG_RESLUT_FIELD}
LOGINOUTMSG.is_extendable = false
LOGINOUTMSG.extensions = {}

LoginOutMsg = protobuf.Message(LOGINOUTMSG)

TestInfo_pb.lua

-- Generated By protoc-gen-lua Do not Edit
local protobuf = require "protobuf"
module('TestInfo_pb',package.seeall)


TESTINFOPROTO = protobuf.Descriptor();
local TESTINFOPROTO_BOOL_FIELD = protobuf.FieldDescriptor();
local TESTINFOPROTO_INT_FIELD = protobuf.FieldDescriptor();

TESTINFOPROTO_BOOL_FIELD.name = "bool"
TESTINFOPROTO_BOOL_FIELD.full_name = ".TestInfoProto.bool"
TESTINFOPROTO_BOOL_FIELD.number = 1
TESTINFOPROTO_BOOL_FIELD.index = 0
TESTINFOPROTO_BOOL_FIELD.label = 1
TESTINFOPROTO_BOOL_FIELD.has_default_value = false
TESTINFOPROTO_BOOL_FIELD.default_value = false
TESTINFOPROTO_BOOL_FIELD.type = 8
TESTINFOPROTO_BOOL_FIELD.cpp_type = 7

TESTINFOPROTO_INT_FIELD.name = "int"
TESTINFOPROTO_INT_FIELD.full_name = ".TestInfoProto.int"
TESTINFOPROTO_INT_FIELD.number = 2
TESTINFOPROTO_INT_FIELD.index = 1
TESTINFOPROTO_INT_FIELD.label = 1
TESTINFOPROTO_INT_FIELD.has_default_value = false
TESTINFOPROTO_INT_FIELD.default_value = 0
TESTINFOPROTO_INT_FIELD.type = 5
TESTINFOPROTO_INT_FIELD.cpp_type = 1

TESTINFOPROTO.name = "TestInfoProto"
TESTINFOPROTO.full_name = ".TestInfoProto"
TESTINFOPROTO.nested_types = {}
TESTINFOPROTO.enum_types = {}
TESTINFOPROTO.fields = {TESTINFOPROTO_BOOL_FIELD, TESTINFOPROTO_INT_FIELD}
TESTINFOPROTO.is_extendable = false
TESTINFOPROTO.extensions = {}

TestInfoProto = protobuf.Message(TESTINFOPROTO)

调用方法示例

image.png

调试结果

image.png

注意事项

一、.proto 文件不能重名,必须保证名字唯一,因为这里的module 使用了文件名。

工具下载路径

参考

protoc-gen-lua多个proto嵌套的实现
protoc-gen-lua 编译、安装、使用教程
Lua中module函数的作用和用法
工具下载protoToLua

上一篇下一篇

猜你喜欢

热点阅读