本文發表於程序員劉宇的博客,轉載請註明來源:http://www.javashuo.com/article/p-giauofyv-gm.htmlhtml
前言android
protobuf做爲一種通用套接字格式,各類插件裏,最本質、最關鍵的就是基於二進制的兩個操做:ios
1. 根據proto文件打包出二進制數據。c++
2. 根據二進制數據反串化出須要的數據格式。 git
因此其實在不一樣平臺下須要的就是各自的解析庫。做爲跨平臺的套接字,同版本二進制打包出來的格式必須徹底同樣,1裏的proto文件通常也是要在項目開發中多平臺通用,2裏反串化的格式是當前語言和環境下的格式。在lua環境裏,通常反串化出來的就是table。程序員
因爲官方並無給lua支持,因此你們各自發揮,使用的比較多的有4種:github
1. pbc-lua: 雲風早期寫的解析庫,解析官方protoc.exe生成的pb,缺點是隻解析一層。json
2. sproto: 雲風(真是孜孜不倦高產出)強推的第二版協議,其實已經不能徹底說是proto,而是一種新套接字,只是兼容。這是他本身關於sproto的說明: https://blog.codingnow.com/2015/04/sproto_rpc.htmlapi
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沒有什麼區別了,這篇入門到此結束。