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;
网友评论