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,所以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