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

【学习笔记】从零开始学ToLua(四)tolua原理解析

[复制链接]
发表于 2021-8-19 07:23 | 显示全部楼层 |阅读模式
lua调用C#


  • tolua中lua调用C#是基于去反射。把所有的c#类的public成员变量、成员函数,都导出到一个相对应的Wrap类中,而这些成员函数通过特殊的标记,映射到lua的虚拟机中,当在lua中调用相对应的函数时候,直接调用映射进去的c# wrap函数,然后再调用到实际的c#类,完成调用过程。当lua虚拟机启动的时候,会将此wrap文件加载进lua虚拟机,然后lua就可以识别此调用了。最后就形成了Lua 调用 Wrap , Wrap调用C#的模式,实现了Lua调用C#

生成wrap文件

    生成Wrap文件需要使用者自己手动的去CustomSetting,填写需要Wrap的文件

    BindLua.cs 文件,里面有个叫Binding的函数,我们手动填写要绑定的类型会被添加到里面的list的里。那里面会通过GenLuaBinders绑定wrap并注册到虚拟机

lua中对C#对象的交互

ObjectTranslator.cs
这个类代码不多,它存在的主要意义就是给lua中对C#对象的交互提供了基础,简单来说就是C#中的对象在传给lua时并不是直接把对象暴露给了lua,而是在这个OjbectTranslator里面注册并返回一个索引(可以理解为windows编程中的句柄)并把这个索引包装成一个userdata传递给lua,并且设置元表。具体可以查看tolua_pushnewudata代码。
而在lua需要通过上面传到lua里面的对象调用C#的方法时,它会调用ToLua.CheckObject或者ToLua.ToObject从ObjectTranslator获取真正的C#对象。
C#与Lua数据交互(lua虚拟栈)

    C#与lua的数据交互是基于一个Lua先进后出的虚拟栈可以压入数字,字符串,表table,闭包func
C#与Lua通信(P/Invoke)

    所有的通信都是基于P/Invoke模式(性能低)类似JNIP/Invoke:公共语言运行库(CLR)的interop功能(称为平台调用(P/Invoke))命名空间:System.Runtime.InteropServices

tolua的优化方式汇总

    BinderLua太多wrap很慢(反射与去反射共存)Lua代码打入AssetBundle为了绕过苹果检测动态注册Wrap文件到Lua虚拟机(tolua延伸)ToLuaExport. memberFilter的函数过滤尽量减少c#调用lua的次数来做主题优化思想尽量使用lua中的容器table取代c#中的所有容器例子CallLuaFunction_02里附带了no gc alloc调用方式Lua的bytecode模式性能要低于Lua源码执行取消动态参数:打开LuaFunction.cs文件,找到函数声明:
  1. public object[] Call(params object[] args){
  2.     return call(args, null);
  3. }
复制代码
取消动态参数args,可用较笨方法,就是定义6-7个默认参数,不够再加。
    安卓平台如果使用luajit的话,记得在lua最开始执行的地方请开启 jit.off(),性能会提升N倍。记得安卓平台上在加上jit.opt.start(3),相当于c++程序-O3,可选范围0-3,性能还会提升。Luajit作者建议-O2

tolua部分代码说明

tolua#的核心运行时

tolua#的运行代码包含SourceGenerate下面的绑定代码以及ToLuaàBaseType代码以及Core下面的核心代码。接下来我们着重讲一下Core下面的几个主要类。
LuaAttribute.cs
它在tolua#生成绑定代码时做一些标示使用。Attribute 是一种可由用户自由定义的修饰符(Modifier),可以用来修饰各种需要被修饰的目标。特性Attribute 的作用是添加元数据。元数据可以被工具支持,比如:编译器用元数据来辅助编译,调试器用元数据来调试程序。Unity以及tolua#中就会用Attribute来辅助做一些事情。
LuaBaseRef.cs
Lua中对象对应C#中对象的一个基类(子类有LuaTable,LuaFunction,LuaThread),主要作用是有一个reference指向lua里面的对象,引用计数判断两个对象是否相等等。
LuaDll.cs
这个类的主要作用就是实现了C#调用原生代码的功能.
LuaState.cs
这里面是对真正的lua_State的封装,包括初始化lua路径,加载相应的lua文件,注册我们前面生成的绑定代码以及各种辅助函数。
ObjectTranslator.cs
接下来,我们着重说一下这个ObjectTranslator这个类,这个类代码不多,它存在的主要意义就是给lua中对C#对象的交互提供了基础,简单来说就是C#中的对象在传给lua时并不是直接把对象暴露给了lua,而是在这个OjbectTranslator里面注册并返回一个索引(可以理解为windows编程中的句柄)并把这个索引包装成一个userdata传递给lua,并且设置元表。具体可以查看tolua_pushnewudata代码。
而在lua需要通过上面传到lua里面的对象调用C#的方法时,它会调用ToLua.CheckObject或者ToLua.ToObject从ObjectTranslator获取真正的C#对象。
userdata
userdata实际上是一个指针地址,通过对这个userdata设置不同的metatable来区分userdata对应的c#类型
要更详细地了解userdata内容可以阅读   tolua#中的userdata @xsxjin

参考资料 http://richbabe.top/2018/07/20/ulua-tolua%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90/ @RichBaby
https://www.cnblogs.com/yptianma/p/11797925.html @天马yp
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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