1. 程式人生 > >騰訊開源手遊熱更新方案Xlua嚐鮮(三)——C#訪問Lua

騰訊開源手遊熱更新方案Xlua嚐鮮(三)——C#訪問Lua

C#訪問Lua

這裡指的是C#主動發起對Lua資料結構的訪問。

一、獲取一個全域性基本資料型別

訪問LuaEnv.Global就可以了,上面有個模版Get方法,可指定返回的型別。

luaenv.Global.Get<int>("a");
luaenv.Global.Get<string>("a");
luaenv.Global.Get<bool>("a");

二、訪問一個全域性的table

也是用上面的Get方法,那型別要指定成啥呢?

1、對映到普通class或struct

定義一個class,有對應於table的欄位的public屬性,而且有無引數建構函式即可,比如對於{f1 = 100, f2 =100}可以定義一個包含publicint f1;public int f2;的class。

這種方式下xLua會幫你new一個例項,並把對應的欄位賦值過去。

table的屬性可以多於或者少於class的屬性。可以巢狀其它複雜型別。

要注意的是,這個過程是值拷貝,如果class比較複雜代價會比較大。而且修改class的欄位值不會同步到table,反過來也不會。

這個功能可以通過把型別加到GCOptimize生成降低開銷,詳細可參見配置介紹文件。

那有沒有引用方式的對映呢?有,下面這個就是:

2、對映到一個interface

這種方式依賴於生成程式碼(如果沒生成程式碼會拋InvalidCastException異常),程式碼生成器會生成這個interface的例項,如果get一個屬性,生成程式碼會get對應的table欄位,如果set屬性也會設定對應的欄位。甚至可以通過interface的方法訪問lua的函式。

3、更輕量級的by value方式:對映到Dictionary<>,List<>

不想定義class或者interface的話,可以考慮用這個,前提table下key和value的型別都是一致的。

4、另外一種by ref方式:對映到LuaTable類

這種方式好處是不需要生成程式碼,但也有一些問題,比如慢,比方式2要慢一個數量級,比如沒有型別檢查。

三、訪問一個全域性的function

仍然是用Get方法,不同的是型別對映。

1、對映到delegate

這種是建議的方式,效能好很多,而且型別安全。缺點是要生成程式碼(如果沒生成程式碼會拋InvalidCastException

異常)。

delegate要怎樣宣告呢?

對於function的每個引數就宣告一個輸入型別的引數。

多返回值要怎麼處理?從左往右對映到c#的輸出引數,輸出引數包括返回值,out引數,ref引數。

引數、返回值型別支援哪些呢?都支援,各種複雜型別,out,ref修飾的,甚至可以返回另外一個delegate。

delegate的使用就更簡單了,直接像個函式那樣用就可以了。

2、對映到LuaFunction

這種方式的優缺點剛好和第一種相反。

使用也簡單,LuaFunction上有個變參的Call函式,可以傳任意型別,任意個數的引數,返回值是object的陣列,對應於lua的多返回值。

四、使用建議

1、訪問lua全域性資料,特別是table以及function,代價比較大,建議儘量少做,比如在初始化時把要呼叫的luafunction獲取一次(對映到delegate)後,儲存下來,後續直接呼叫該delegate即可。table也類似。

2、如果lua測的實現的部分都以delegate和interface的方式提供,使用方可以完全和xLua解耦:由一個專門的模組負責xlua的初始化以及delegate、interface的對映,然後把這些delegate和interface設定到要用到它們的地方。