找回密码
 立即注册
查看: 449|回复: 0

Lua:来讲一下包装类在虚拟机内部的调用逻辑和userdata的存储对象

[复制链接]
发表于 2021-8-19 07:37 | 显示全部楼层 |阅读模式
首先,感谢蒙哥让我能用上这么方便的一个lua框架-tolua
我想大家在使用tolua的时候,在做c#包装类(即wrap文件的时候),都会不由的感叹,原来lua和c#交互竟然那么简单,那么请问有谁真正的了解过这些wrap文件的原理,这些文件又是如何在虚拟机之中运行的呢,intptr这个类的作用又是什么,里面的topointer方法有没有想过之间隐藏的含义,那么我接下来会慢慢bb的。

阅读一下部分,请了解lua寄存器虚拟机的基础知识,不明白可以看我上一篇文章最前面部分关于lua虚拟机介绍,有了这个概念你才可以继续阅读

1.tolua如何将c#对象导入到lua里

tolua为每一个传入lua的对象建立一个userdata,userdata的值,是c#对象的地址。userdata的metatable,是一个tolua建立的,记录了userdata对应c#类型信息的表格,包括导出的成员变量、成员函数等信息。

对于成员变量的读取赋值,tolua是在metatable里新建了.get和.set两个表。两个表里分别存储了以变量名为键,以读取设置c #函数为值的表项。在metatable的__index和__newindex里,以变量名为键,从.get和.set表里取得读取设置函数并调用。



传入c#对象的tolua函数是tolua_pushusertype。一般情况下,第一次使用这个函数将一个c#对象push到lua堆 栈上时,才会新建userdata。tolua会以c#对象地址为键,userdata为值,将键值对存储在tolua_ubox表里。下次推入同 样的c#对象时,从这个表里取出userdata推入堆栈即可。




我导入一个之前wrap类型的函数做介绍

[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]

static int Create(IntPtr L)

{

    try

    {

       Tolua.CheckArgsCount(L,3);

       Cos.Battlefield.BattlefieldManager obj = (
Cos.Battlefield.BattlefieldManager
) ToLua.CheckObject<Cos.Battlefiled.BattlefieldManager>(L,1);

       LuaTable arg0 = ToLua.CheckLuaTable(L,2);

       LuaTable arg1 = ToLua.CheckLuaTable(L,3);

       obj.Create(arg0,arg1);

       return 0;

     }

      catch(Exception e)

      {

         return LuaDll.toluaL_exception(L,e);

       }

}

请结合文字加上这个wrap类方法代码,想一下文字里面的逻辑,然后再继续看,自己的理解有时候即使错误也比直接给答案的意义要大得多



现在,你大概知道了这个IntPtr是什么玩意了,我查了下百度(~ !~),解释如下

用于表示指针或句柄的平台特定类型。
**命名空间:**System
**程序集:**mscorlib(在 mscorlib.dll 中)

链接:https://docs.microsoft.com/zh-cn/previous-versions/dotnet/netframework-1.1/5he14kz8(v=vs.80)
那么我们lua调用一个c#对象的原理就很简单过,首先创建或者获取
传入c#对象的tolua函数是tolua_pushusertype。一般情况下,第一次使用这个函数将一个c#对象push到lua堆 栈上时,才会新建userdata。tolua会以c#对象地址为键,userdata为值,将键值对存储在tolua_ubox表里。下次推入同 样的c#对象时,从这个表里取出userdata推入堆栈即可。


然后调用,调用首先要把userdata压入堆栈,所以上面c#代码里面参数IntPtr就是一个内存地址,然后通过
Tolua.CheckArgsCount(L,3);拿到了这块内存地址的
BattlefieldManager 对象和lua传递过来的两个参数(因为L内存地址顺序是连续的)

LuaTable arg0 = ToLua.CheckLuaTable(L,2);

LuaTable arg1 = ToLua.CheckLuaTable(L,3);

最后使用这个对象,传入参数,调用方法,执行完毕,这样你是否对于tolua的理解更深一步了呢,如果有小伙伴希望了解lua的知识,可以留言,我会的会在评论中回复,谢谢观看

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 12:11 , Processed in 0.290075 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表