1. 程式人生 > >Tolua使用筆記二:lua與C#的函式,變數互動方法

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型別的物件

func.Dispose();方法,釋放掉垃圾記憶體,否則會造成記憶體洩漏。

2:如樣例中的CallFunc()所示,程式碼如下:

int CallFunc()
    {        
        func.BeginPCall();                
        func.Push(123456);
        func.PCall();        
        int num = (int)func.CheckNumber();                    
        func.EndPCall();
        return (int)num;        
    }
使用方法非常麻煩,必須要先以func.BeginPCall();開使,通過func.Push(引數)來給方法傳參,然後需要通過這一步 func.PCall();  來執行 , 最後通過對應的func.Check xxx()方法來獲取返回值,最後還要通過func.EndPCall();結束 , 整個流程比較繁瑣且不是很容易封裝,不過優點是不會有垃圾記憶體,所以不用手動釋放GC。


案例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();

說到到這裡就差不多了,後面的咱們下回分解

生氣生氣生氣生氣