XLua实现原理-02

608 阅读3分钟

「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」。

作为一名优秀的开发者,对于技术的探求应该是永无止步的,如何让自己更进步,那就只有不停的学习,不停的充电.而这些都都是说起来容易做起来难,坚持才是难的地方 --蛙哈哈

XLua实现原理-02

1.先来一个简单示例

    public class Helloworld : MonoBehaviour
    {
        // Use this for initialization
        void Start()
        {
            LuaEnv luaenv = new LuaEnv();
            luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");
            luaenv.Dispose();
        }
    }

LuaEnv luaenv = new LuaEnv();

先创建一个Lua虚拟机.

luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");

再用虚拟机执行Lua代码

2.Lua和C#是怎么交互的

首先我们要知道的是,lua本身提供了C_API,让我们push一个值到lua虚拟栈上。lua可以通过访问lua虚拟栈,

来访问这个对象。

Lua虚拟栈是lua和其他语言交换数据的中介。

由于C和lua中的数据结构是完全不一样的,并且lua函数可以返回多个结果,所以要有一种在lua脚本和C函数

之间交换数据的机制,这个机制就是虚拟栈.

这个栈可以储存任何类型的数据,供lua调用的C函数从这个栈中获取调用参数,然后将结果再压入栈中返回到

lua,这个虚拟栈用索引来操作.

image-20220217223337982.png xlua对以上接口进行了封装,并同样提供了一系列的push方法,让我们可以把一个c#对象push到lua的虚拟栈上。

可以把xlua的push API归为两类:一类是针对某种特定类型的push,暂且叫做LowLevelAPI;

还有一类是基于LowLevelAPI封装的更上层的HighLevelAPI。

image-20220217223355700.png

传递基元类型

编译器直接支持的数据类型称为基元类型(primitive type)。基元类型直接映射到Framework类库(FCL)中存在的类型。

FCL类型在C#中对应的基元类型:

Boolean、Byte、SByte、Int16、UInt16、Int32、UInt32、Int64、UInt64、IntPtr、UIntPtr、Char、Double和 Single。

从某个角度来说,可以认为C#编译器自动为所有源代码文件添加using指令为类型创建别名。

using int = System.Int32;

image-20220217223416155.png

image-20220217223503127.png

image-20220217223750971.png

为什么我们传给lua的对象是一个int类型(这里的key)?

其实我们这里的key是我们要传递的c#对象的一个索引,我们可以通过这个索引找到这个c#对象

当传递一个c#对象的时候,我们创建一个userdate,并把这个索引值赋给这个userdata。

然后,lua在全局注册表中,有一张专门的表用来存放c#各种类型所对应的元表,

而meta_ref就是当前这个对象所对应类型的元表的索引id,

我们通过他找到对应的元表,就可以通过setmetatable来绑定操作这个对象的方法。

最终lua就可以愉快的使用这个对象。