xLua下使用lua-protobuf


本文發表於程序員劉宇的博客,轉載請注明來源:https://www.cnblogs.com/xiaohutu/p/12168781.html

 

前言

protobuf作為一種通用套接字格式,各種插件里,最本質、最關鍵的就是基於二進制的兩個操作:

1. 根據proto文件打包出二進制數據。

2. 根據二進制數據反串化出需要的數據格式。 

所以其實在不同平台下需要的就是各自的解析庫。作為跨平台的套接字,同版本二進制打包出來的格式必須完全一樣,1里的proto文件一般也是要在項目開發中多平台通用,2里反串化的格式是當前語言和環境下的格式。在lua環境里,一般反串化出來的就是table。

由於官方並沒有給lua支持,所以大家各自發揮,使用的比較多的有4種:

1. pbc-lua: 雲風早期寫的解析庫,解析官方protoc.exe生成的pb,缺點是只解析一層。

2. sproto: 雲風(真是孜孜不倦高產出)強推的第二版協議,其實已經不能完全說是proto,而是一種新套接字,只是兼容。這是他自己關於sproto的說明: https://blog.codingnow.com/2015/04/sproto_rpc.html

3. protoc-gen-lua: seanlin寫的插件,這個大家用的也多,ulua,tolua的很多項目都用這個。原理是生成lua端的.lua描述文件,打包時先使用描述文件的定義來New,然后Serialize。只支持到5.1,后面就沒有維護了。

4. lua-protobuf: 這個現在大家用的多,是目前在莉莉絲工作的starwing寫的,這個使用起來也很簡單,可以讀pb,也可以直接讀定義文件(性能捉急),然后直接在lua按照proto格式寫table,encode就行了。 

下面說說如何接入lua-protobuf插件,參考鏈接:

xLua官方:https://github.com/Tencent/xLua

xLua官方集成第三方庫:https://github.com/chexiongsheng/build_xlua_with_libs

lua-protobuf:https://github.com/starwing/lua-protobuf

 

編庫文件

1. 首先是要獲得庫文件,先去集成的git下查看一下版本,有一些已經編號的是否可以用,里面是根據xlua的版本來保存了一些編好的庫,具體有ffi,lpeg,rapidjson,lua-protobuf,pbc(chexiongsheng大佬貼心)。

 

2. 沒有現成的版本也沒關系,我們把相關的庫和xlua的源碼一起編一下就行了。先拿下第三方庫的svn,再把我們實際使用的那個版本的xlua源碼下下來(如:https://github.com/Tencent/xLua/tree/master/build),拷到本地下好的build_xlua_with_libs文件夾里。然后根據平台分別編譯.安卓下NDK,cmake,ninja,AndroidSDK,JDK統統安裝好,點擊make_android_lua53.bat,PC下的先安裝好cmake和c++的vs環境,點擊make_win64_lua53.bat,MAC下先"chmod 777 make_ios_lua53.sh",然后執行 "./make_ios_lua53.sh"。編完了以后plugin_lua53\Plugins下就有各平台的庫文件啦。

 

 

把庫文件加入項目

1. 使用xLua提供的加載靜態庫方法AddBuildin,這個方法可以指定在lua側指定特定庫文件名在C#端的加載方法,並且限定了格式: 

1 public void AddBuildin(string name, LuaCSFunction initer)
2  //name:buildin模塊的名字,require時輸入的參數;
3  //initer:初始化函數,原型是這樣的public delegate int lua_CSFunction(IntPtr L),必須是靜態函數,
4  //而且帶MonoPInvokeCallbackAttribute屬性修飾,這個api會檢查這兩個條件。

 2. 接着我們在某個地方定義一下這個LuaCSFunction,一般是在LuaDLL.cs里,這里把luaopen_pb這個方法extern過來,寫進了LoadPb里 

復制代碼
 1 namespace LuaDLL
 2 { 
 3     public partial class Lua
 4     {
 5         [DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
 6         public static extern int luaopen_pb(System.IntPtr L);
 7 
 8         [MonoPInvokeCallback(typeof(LuaDLL.lua_CSFunction))]
 9         public static int LoadPb(System.IntPtr L)
10         {    
11             return luaopen_pb(L);  
12         }
13     }
14 }
復制代碼

 3. 准備完畢后,在我們lua端的初始化的地方添加加載這個"pb"庫的方法:

1 LuaEnv luaenv = new LuaEnv();
2 luaenv.AddBuildin("pb", XLua.LuaDLL.Lua.LoadPb);
3 --luaenv.AddBuildin("rapidjson", XLua.LuaDLL.Lua.LoadRapidJson);

 4. 這樣的話在lua中再require 'pb'的時候就會自動調用pb庫

1 -- 加載pb文件
2 local pb = require "pb"

好了接下來就可以寫網路框架代碼了。

 

框架代碼接入

1. 先加載proto結構定義,前面提到可以加載pb或者proto.Schema結構,分別如下:

    第一種大家都熟悉,編一下pb文件,使用loadfile加載

1 -- 加載pb文件,需要把proto編成pb使用
2 local pb = require "pb"
3 assert(pb.loadfile "login.pb")

    第二種是我使用的,因為是Schema結構,做成文本文件方便結合資源系統更新

復制代碼
1 local pb = require "pb"
2 local protoc = require "protoc" --protoc在lua-protobuf的目錄里 
3 
4 local protoString = ResLoader.Instance:LoadLuaProtoFile('login.proto.txt') --用自己的資源系統加載文本格式文件
5 protoc:load(protoString) --加載文本文件的內容
復制代碼

 2. 使用pb解碼,編碼協議。這一步就是標准的流程了,lua-protobuf可以直接對定義好的結構decode/encode:

復制代碼
 1 -- 定義表數據
 2 local loginCS = {
 3     username="jack",
 4     password="123456",
 5 }
 6 
 7 -- 序列化
 8 local bytes = assert(pb.encode("login.req_login", loginCS))
 9 print(pb.tohex(bytes))
10 
11 -- 反序列化
12 local recvData = assert(pb.decode("login.req_login", bytes))
13 print(recvData .username)
復制代碼

 到這就跟以前其他平台使用protobuf沒有什么區別了,這篇入門到此結束。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM