Tolua使用筆記二:lua與C#的函式,變數互動方法
接著上一回的接著講:
案例三:
到這裡久終於到了大家最感興趣的地方了,熱更新的價值就在於用指令碼語言寫邏輯,這樣可以實現邏輯的頻繁改動而不用每次更新都重新下載。
而這個過程中必然涉及到C#對lua的一個邏輯呼叫,而這個例子實現的就是C#的函式的呼叫
核心程式碼如下:
效果圖如下:private string script = @" function luaFunc(num) return num + 1 end test = {} test.luaFunc = luaFunc "; LuaFunction func = null; LuaState lua = null; void Start () { lua = new LuaState(); lua.Start(); lua.DoString(script); //Get the function object func = lua.GetFunction("test.luaFunc"); if (func != null) { //有gc alloc object[] r = func.Call(123456); Debugger.Log(r[0]); // no gc alloc int num = CallFunc(); Debugger.Log(num); } lua.CheckTop(); } int CallFunc() { func.BeginPCall(); func.Push(123456); func.PCall(); int num = (int)func.CheckNumber(); func.EndPCall(); return (int)num; }
對於本章,主要的知識點如下:
1:對於lua的函式在C#中的呼叫,首先在lua中函式是一個物件(嚴格意義上說C#裡面也算是物件吧~~),在虛擬機器初始化完成後,載入了對應的lua檔案之後,必須要建立一個LuaFunction型別的物件,通過呼叫 lua.GetFunction("方法名"); 獲取lua檔案中對應的函式物件,接下來就是呼叫了
C#中呼叫lua函式的方法有2種:
1:直接呼叫LuaFunction型別的物件的func.Call 方法,完整宣告為:public object[] Call(params object[] args)
這種呼叫方法比較簡單,但是為一個缺點,lua物件的記憶體無法被自動釋放,所以當使用完這個lua物件之後,我們需要手動的呼叫LuaFunction型別的物件
2:如樣例中的CallFunc()所示,程式碼如下:
使用方法非常麻煩,必須要先以func.BeginPCall();開使,通過func.Push(引數)來給方法傳參,然後需要通過這一步 func.PCall(); 來執行 , 最後通過對應的func.Check xxx()方法來獲取返回值,最後還要通過func.EndPCall();結束 , 整個流程比較繁瑣且不是很容易封裝,不過優點是不會有垃圾記憶體,所以不用手動釋放GC。int CallFunc() { func.BeginPCall(); func.Push(123456); func.PCall(); int num = (int)func.CheckNumber(); func.EndPCall(); return (int)num; }
案例4:
這個案例主要是介紹C#中如何獲取,宣告,使用lua中的變數,核心程式碼如下:(這次好像又是難得的整篇程式碼都是重點)
public class AccessingLuaVariables : MonoBehaviour
{
private string script =
@"
print('Objs2Spawn is: '..Objs2Spawn)
var2read = 42
varTable = {1,2,3,4,5}
varTable.default = 1
varTable.map = {}
varTable.map.name = 'map'
meta = {name = 'meta'}
setmetatable(varTable, meta)
function TestFunc(strs)
print('get func by variable')
end
";
void Start ()
{
LuaState lua = new LuaState();
lua.Start();
lua["Objs2Spawn"] = 5;
lua.DoString(script);
//通過LuaState訪問
Debugger.Log("Read var from lua: {0}", lua["var2read"]);
Debugger.Log("Read table var from lua: {0}", lua["varTable.default"]);
LuaFunction func = lua["TestFunc"] as LuaFunction;
func.Call();
func.Dispose();
//cache成LuaTable進行訪問
LuaTable table = lua.GetTable("varTable");
Debugger.Log("Read varTable from lua, default: {0} name: {1}", table["default"], table["map.name"]);
table["map.name"] = "new";
Debugger.Log("Modify varTable name: {0}", table["map.name"]);
table.AddTable("newmap");
LuaTable table1 = (LuaTable)table["newmap"];
table1["name"] = "table1";
Debugger.Log("varTable.newmap name: {0}", table1["name"]);
table1.Dispose();
table1 = table.GetMetaTable();
if (table1 != null)
{
Debugger.Log("varTable metatable name: {0}", table1["name"]);
}
object[] list = table.ToArray();
for (int i = 0; i < list.Length; i++)
{
Debugger.Log("varTable[{0}], is {1}", i, list[i]);
}
table.Dispose();
lua.CheckTop();
lua.Dispose();
}
}
效果圖如下:
這個案例中主要的知識點如下:
1:建立lua虛擬機器的全域性變數: 在lua虛擬機器建立完成且初始化完畢(呼叫Start方法)之後,可以直接通過以下格式宣告一個lua虛擬機器的全域性變數 lua["變數名"] = 值; 則建立了一個名為 變數名 的 lua全變數,值為 右式的值
2:訪問 lua的變數,和建立lua虛擬機器的變數的格式相同,這一點和lua中關於變數的定義是相同的,如果有就建立,否則就獲取對應的值,其中對於lua中的函式的使用是需要經過強轉,例如lua中的函式 ,具體如下:
LuaFunction func = lua["TestFunc"] as LuaFunction;
3:lua中table的獲取和建立:通過呼叫虛擬機器的方法lua.GetTable 來獲取lua中的table,用LuaTable型別來儲存lua中的Table,通過呼叫Luatable的成員方法table.AddTable來建立lua中的table , 除了通過虛擬機器的GetTable方法我訪問之外,直接通過 LuaTable 型變數按字典的類似方法也可以呼叫tabel , 例如如下:
<span style="color:#FF0000;">LuaTable table1 = (LuaTable)table["newmap"];</span>
對於lua元表也是可以獲取的,方法為呼叫LuaTable的table.GetMetaTable();方法,則可以獲得lua的元表Table注意一下:對LuaTable型的變數,在使用完之後需要手動釋放記憶體,否則會應為記憶體未自動釋放造成記憶體洩露~~~具體方法為呼叫LuaTable物件的方法table.Dispose();
說到到這裡就差不多了,後面的咱們下回分解