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

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