ulua-pbc

作者: passiony | 来源:发表于2018-06-15 17:17 被阅读222次

pbc

它是云风大神早期的一个对protobuf的解析库,相对于protobuf_lua_gen来说,不需要生成巨多的lua协议描述文件,可以直接读取protobuf官方代码编译出来的protoc.exe生成的pb二进制文件,简洁效率还高。所以我们的项目也采用了pbc作为我们的主要通讯协议层。
pbc有两种解析模式:(A)直接读取二进制的pb文件,从里面获取协议描述信息,(B)通过lpeg直接解析协议描述文件。应该是前者效率高于后者。

编译pb二进制文件

到官网去下载protobuf的c源码,编译出protoc.exe来,然后通过下面的命令行编译出pb文件:

protoc.exe -o 目标文件 源文件

我用的2.4.1版本比较老,可以下载最新版自己去编译,如果为了测试可以去ulua.org去下载测试:http://www.ulua.org/download.html

下载地址:
protobuf-2.4.1.zip (d:/protobuf-2.4.1)
顺便说下,使用pblua也需要它的源码编译出来的protoc.exe

编译

修改uLua/Editor/Packager.cs里面BuildProtobufFile函数,即可以编译。

[MenuItem("LuaFramework/Build pbc File")]
    public static void BuildPbcFile()
    {
        string dir = AppDataPath + "/LuaFramework/Lua/3rd/pbc";
        paths.Clear(); files.Clear(); Recursive(dir);
        
        string protoc = "d:/protobuf-2.4.1/src/protoc.exe";
        
        foreach (string f in files)
        {
            string inName = Path.GetFileName(f);
            string outName = Path.GetFileName(f).Replace(".proto", ".pb");
            string ext = Path.GetExtension(f);
            if (!ext.Equals(".proto")) continue;

            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = protoc;
            info.Arguments = " -o "+ outName+" "+inName;
            info.WindowStyle = ProcessWindowStyle.Hidden;
            info.UseShellExecute = true;
            info.WorkingDirectory = dir;
            info.ErrorDialog = true;
            Util.Log(info.FileName + " " + info.Arguments);

            Process pro = Process.Start(info);
            pro.WaitForExit();
        }
        AssetDatabase.Refresh();
    }

测试发送pbc

function PromptCtrl.TestSendPbc()
    local path = Util.DataPath.."lua/3rd/pbc/addressbook.pb";

    local addr = io.open(path, "rb")
    local buffer = addr:read "*a"
    addr:close()
    protobuf.register(buffer)

    local addressbook = {
        name = "Alice",
        id = 12345,
        phone = {
            { number = "1301234567" },
            { number = "87654321", type = "WORK" },
        }
    }
    local code = protobuf.encode("tutorial.Person", addressbook)
    ----------------------------------------------------------------
    local buffer = ByteBuffer.New();
    buffer:WriteByte(ProtocalType.PBC);
    buffer:WriteBuffer(code);
    NetManager:SendMessage(buffer);
end

测试接收pbc

function Network.TestLoginPbc(buffer)
    local protocal = buffer:ReadByte();
    local data = buffer:ReadBuffer();
    local path = Util.DataPath.."lua/3rd/pbc/addressbook.pb";
    local addr = io.open(path, "rb")
    local buffer = addr:read "*a"
    addr:close()
    protobuf.register(buffer)
    local decode = protobuf.decode("tutorial.Person" , data)

    print(decode.name)
    print(decode.id)
    for _,v in ipairs(decode.phone) do
        print("\t"..v.number, v.type)
    end
    log('TestLoginPbc: protocal:>'..protocal);
end

使用pbc有个非常重要的一个问题,我不知道应不应该定位为bug,至少“云风大神”认为是个问题,但是不想改,我这里也附上解决方案,假如你有这么个消息,里面有个数组类型的repeat类型的数据字段,服务器连续发给你2次这个消息,而且里面一个成员字段的值都没有的话,pbc这两次给你的结构table是同一个内存指针地址,而不是每次都新分配的table。解决方案:你在接收这个数据之前,自己提前将数据表结构布局好,至少被copy的数据table要有个自己新建的空表{},才能导致数据不会串。如下:

local data["aaa"] = {};
data["aaa"] = buffer.data;

相关文章

  • ulua-pbc

    pbc 它是云风大神早期的一个对protobuf的解析库,相对于protobuf_lua_gen来说,不需要生成巨...

网友评论

      本文标题:ulua-pbc

      本文链接:https://www.haomeiwen.com/subject/tdmmeftx.html