lua與其他語言交互,都是通過操作虛擬棧交流的。而操作虛擬棧最原始的方法就是通過lua與c語言的api,由於直接操作lua與c比較繁瑣而且容易出錯。因此tolua作為中間層而存在。
那么unity要把一個C#對象傳遞到lua里面,要怎么做呢?
1. 調用接口Tolua.Push(L,obj);這里的L指的是對應的luastate,obj就是c#對象;
• luastate 中放的是lua虛擬機中環境表、注冊表、運行堆棧、虛擬機的上下文等數據。
•從一個主線程(特指lua虛擬機中的線程,即coroutine)中創建出來的新的luaState會共享大部分數據,但會擁有一個獨立的運行堆棧。所以一個線程對象擁有一個luaState。
2. 如果 obj == null,會調用原生api(lua_pushnil(L,-1))把一個nil值壓入棧頂,所以c#這邊為null,lua那邊會接收到一個nil值;如果obj 不為null,通過obj.GetTYpe()獲取obj的類型,為了便於理解,姑且把這個obj認為是GameObject類型;
3. 接下來tolua會去字典查找GameObject在lua中對應的metatable的ref,這個字典的類型為Dictionary<Type,int>,所以ref是一個int類型的值。說到這里,可能會有兩個疑點,a.這個metatable是什么東西?b. 這個metatable的ref又是什么東西?
我們都知道,如果在lua中使用C#對象,要生成對應的xxxwrap.cs文件,這些wrap文件都是一些static方法,用來和luastate進行綁定,然后就可以在lua中調用c#對象了。在綁定一個C# Class
的時候,會調用BeginClass(tolua_beginclass)來告訴lua我要綁定一個class。
其實在beginclass之前,會先調用beginmodule,比如beginmodule(“UnityEngine”),意思是在lua創建一個全局table,這個table名字就叫UnityEngine。並設置package.load["UnityEngine"] = UnityEngine