ULua反射原理——自我理解,有问题请斧正,谢谢!
ULua反射原理
- 旧版本ULua
- 使用的类
- 实现方式
- 现版本的ulua(tolua)
- 实现方式
- wrap:What ,How?
- What:wrap是什么
- How :Wrap使用与生成
- How :对于庞大代码块,如何处理不想warp的文件?
(今天在研究ULua反射原理时搜索到的答案,进行的理解。如果后续确认有问题后会及时改正。)
所参考引用的文章 ulua、tolua原理解析
旧版本ULua
使用的类
System.Type类 :访问任何给定数据类型的信息。
System.Reflection.Assembly类 :用于访问给定程序集的信息,或者把这个程序集加载到程序中。
实现方式
lua调用C#是基于C#的反射。通过 System.Reflection.Assembly 把UnityEngine程序集加入到Lua代码中。然后通过 System.Type 查找出需要的类型加入到Lua代码中
private string script = @"
luanet.load_assembly('UnityEngine')
luanet.load_assembly('Assembly-CSharp')
GameObject = luanet.import_type('UnityEngine.GameObject')
ParticleSystem = luanet.import_type('UnityEngine.ParticleSystem') local newGameObj = GameObject('NewObj')
newGameObj:AddComponent(luanet.ctype(ParticleSystem))
";
//反射调用
void Start () {LuaState lua = new LuaState();lua.DoString(script);
}
本质就是 在C#段写个通用反射函数, 然后将地址注册到lua全局表中
现版本的ulua(tolua)
实现方式
lua调用C#是基于去反射。
把所有的c#类的public成员变量、成员函数,都导出到一个相对应的Wrap类中,而这些成员函数通过特殊的标记,映射到lua的虚拟机中,当在lua中调用相对应的函数时候,直接调用映射进去的c# wrap函数,然后再调用到实际的c#类,完成调用过程。
具体可参考Unity3d ulua c#与lua交互+wrap文件理解
wrap调用提升了反射在效率上的不足,但是必须自己去wrap,所以大版本更新是可以用到的,小版本更新目前还是得用到反射
wrap:What ,How?
What:wrap是什么
wrap是对c#类的成员函数,成员变量,通过映射的方式。每个wrap文件都是对一个c#类的包装,在lua中,通过对wrap类中的函数调用,间接的对c#实例进行操作。
源C#文件:
using UnityEngine;
using System.Collections; public class Example { public string E1; public Example (){ } public LoginData(string e1){ this.E1 = e1; } public void Exm(string e1, string password, int id){ if (this.E1.Equals (e1) ) { Debug.Log ("C# >>> Exm= {e1= " + this.E1); } else { Debug.Log ("Error!"); } }
}
wrap后的文件
using System;
using LuaInterface; public class ExampleWrap
{ public static void Register(IntPtr L) { LuaMethod[] regs = new LuaMethod[] { new LuaMethod("Exm", Exm), new LuaMethod("New", _CreateExm), new LuaMethod("GetClassType", GetClassType), }; LuaField[] fields = new LuaField[] { new LuaField("E1", get_E1, set_E1), }; LuaScriptMgr.RegisterLib(L, "Example", typeof(Example), regs, fields, typeof(object)); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int _CreateExample(IntPtr L) { int count = LuaDLL.lua_gettop(L); if (count == 0) { Example obj = new Example(); LuaScriptMgr.PushObject(L, obj); return 1; } else if (count == 1) { string arg0 = LuaScriptMgr.GetString(L, 1); Example obj = new Example (arg0); LuaScriptMgr.PushObject(L, obj); return 1; } else { LuaDLL.luaL_error(L, "invalid arguments to method: Example.New"); } return 0; } static Type classType = typeof(Example ); [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int GetClassType(IntPtr L) { LuaScriptMgr.Push(L, classType); return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_E1(IntPtr L) { object o = LuaScriptMgr.GetLuaObject(L, 1); Example obj = (Example )o; if (obj == null) { LuaTypes types = LuaDLL.lua_type(L, 1); if (types == LuaTypes.LUA_TTABLE) { LuaDLL.luaL_error(L, "unknown member name E1"); } else { LuaDLL.luaL_error(L, "attempt to index E1on a nil value"); } } LuaScriptMgr.Push(L, obj.E1); return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int set_E1(IntPtr L) { object o = LuaScriptMgr.GetLuaObject(L, 1); Example obj = (Example )o; if (obj == null) { LuaTypes types = LuaDLL.lua_type(L, 1); if (types == LuaTypes.LUA_TTABLE) { LuaDLL.luaL_error(L, "unknown member name E1"); } else { LuaDLL.luaL_error(L, "attempt to index E1on a nil value"); } } obj.E1= LuaScriptMgr.GetString(L, 3); return 0; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int Exm(IntPtr L) { LuaScriptMgr.CheckArgsCount(L, 4); Example obj = (Example )LuaScriptMgr.GetNetObjectSelf(L, 1, "Example "); string arg0 = LuaScriptMgr.GetLuaString(L, 2); obj.Equip(arg0); return 0; }
}
流程就是 Lua虚拟机启动时,将Wrap注册加载进去,然后Lua 即可调用 Wrap , Wrap调用C#的模式,实现了Lua调用C#
How :Wrap使用与生成
图源来自tolua之wrap文件的原理与使用
How :对于庞大代码块,如何处理不想warp的文件?
tolua# 不支持动态反射。动态反射对于重载函数有参数匹配问题,函数排序问题,ref,out 参数问题等等。
tolua#提供的替换方法是:
一、preloading, 把你未来可能需要的类型添加到导出列表customTypeList,同时也添加到dynamicList列表中,这样导出后该类型并不会随binder注册到lua中,你可以通过 require “namespace.classname” 动态注册到lua中,对于非枚举类型tolua#系统也可以在第一次push该类型时动态载入,当然也可在过场动画、资源下载、登录、场景加载或者某个的函数中require这个类型。
二、静态反射,参考例子22 GitHub_topameng/tolua。通过静态反射支持精确的函数参数匹配和类型检查。不会存在重载函数参数混乱匹配错误问题, 注意iOS必须配置好link.xml
ULua反射原理——自我理解,有问题请斧正,谢谢!相关推荐
- JavaScript中函数的四种调用方式(若有错误之处请斧正)
函数的几种调用方式 一.一般形式函数的直接调用 fun(); 二.作为对象的方法调用 var obj = {name:"123",sayMyage:function(age){al ...
- 关于OpenGL ES 3D 光晕如何产生的自我理解
2019独角兽企业重金招聘Python工程师标准>>> 星空图的自我理解:可以看作一个透明的半径很大的天球,然后在其表面上绘制大小不一的点,这样便可以够成星空图. 如何产生光晕的自我 ...
- 关于渗透的一些思路持续更新(自我理解)
关于渗透的一些思路持续更新(自我理解) 先回忆一下 准确的是17年才接触到渗透以及ddos 其他hei产东西就不介绍了 接触的自我感觉有点迟 从最开始我也是从阿D明小子那些很傻瓜化的软件走过来的 但是 ...
- 读阿里中台战略思想有感—自我理解
读阿里中台战略思想有感-自我理解 中台的意义在于避免项目工程建设的不断"造轮子",也就是当需求来临时,全部重新建设,核心公共模块的工程代码没有被重复利用. 阿里对于中台战略思想的实 ...
- Sparsity Quantization 之自我理解
Sparsity & Quantization 之自我理解 Sparsity Quantization DNN的最初的动力是以precise为中心,但随着DNN在Edge的推广,Latency ...
- 我的python之路一初识python的自我理解
初识python的自我理解 关于python的自我简记 我认识的python 怎么开始python的学习和使用 我尝试过的几个python学习的常用组合 关于python的自我简记 初识python是 ...
- 六式建站浅见,和大家一起分享,不足之处还望斧正。
和leven(小の鱼)同志一起为广大IT朋友设计的六式资讯分享社区[http://www.sixtp.com],经过反复的锤炼,终成今天的六式第一版,在这里把第一版制作过程中的心得写出来和大家一起分享 ...
- 如何通过c语言获取ipv6邻居表,急求在vc++6.0中获取IPV6地址的方法,高手请进,谢谢!!...
本人最近getaddrinfo函数获取本机IP地址,本机的IPV4地址能正确获得,但本机IPV6地址只能获得环路地址,即::1.为什么不能获得IPV6的Global地址或链路本地地址.恳请指点,不胜感 ...
- c语言编辑学生信息录入的程序,c语言编的学生信息管理系统小程序!!有不足的请指出,谢谢!!...
c语言编的学生信息管理系统小程序!!有不足的请指出,谢谢!! #include #include #include struct st { char name[20]; int english; in ...
最新文章
- Linux使用netstat命令查看并发连接数
- Error running ‘xxx-web-order‘: Unable to open debugger port : java.net.Socke
- SpringBoot-MyBatis
- 十大排序算法之快速排序(两种方法)
- 网站服务器需要定期重启吗,定期服务器重启的好处和障碍
- Access 时间比较错误
- java中关键字、标识符、常量、变量、数据类型
- 中移动飞信2010Beta1.0体验版
- Unity中的layer和tag
- PTA 程序设计天梯赛(61~80题)
- 浏览器调试动态js脚本
- python 爬虫库 u_9个用来爬取网络站点的 Python 库
- 浅谈LBP原理和代码(基于Python)
- 改文件777的php,服务器文件目录权限777修改方法
- unity 遮挡剔除
- 【随便做做|线段树】POJ3667 Hotel
- ​​​​​​​排列组合基本原理及公式
- 一位想学习编程拯救他人的初中生
- linux用户禁止登录,Linux限制用户登录
- 在线学习系统源代码_学习系统设计和软件体系结构必看的5门在线免费课程