Xlua Wrap

本文详细探讨xlua采用的wrap系统,通过C#的中间层文件实现C#与lua的通信,涉及委托、枚举、接口和类的转换,以及TemplateEngine.cs中的正则表达式匹配,展示了wrap文件的生成过程和映射规则。
摘要由CSDN通过智能技术生成

鉴于上个对xlua与C#的各方面初探有些笼统,本次只在一个方面进行较深层次的解释和讨论:xlua的wrap系统。

xlua的wrap系统

首先需要明确一点:lua和C#之间一定有一个桥梁使其能够正常通信,无非两种手段:

要么将C#转成lua代码然后在lua侧,只保留一小部分C#代码控制其运转;

要么生成中间层文件,lua代码通过C#端的这些中间层文件进行交互。然后在C#侧控制其运转。

对于第一种手段遇到的问题显然很多,比如委托、接口、抽象类等等C#这种解释性语言才有的机制,转成非常轻量的脚本语言,这其中的映射建立是非常困难的。

xlua采用了第二种机制,将lua要用到的C#以wrap文件的形式转至中间层,再由xlua的其他控制系统控制运作。

xlua之外:tolua的机制和xlua很类似,通过ToLuaExport.cs实现对C#代码的中间文件生成操作。

Generate wrap

对于创建wrap相关的文件应该从Generator.GenAll()开始看。

在这里可以看到非常重要的几个函数:

GenDelegateBridges(args);
GenEnumWraps();
GenCodeForClass();
GenLuaRegister();

顾名思义,分别是生成需要导出的委托、枚举、接口、类对应的wrap文件以及中央控制器Register,用于运行时找到对应类型的wrap文件,并执行该文件的__Registera方法,这个方法会把这个类的静态方法、成员方法注册到lua表里。

在这里多说一下具有代表性的函数GenCodeForClass(),看名称应当是类的转换,但实际上还包括interface类型的转换,因其里面有一句:

var itf_bridges_types = CSharpCallLua.Where(type => type.IsInterface).Distinct();

当然,内部依然还有结构体的封装转换等等:

GenPackUnpack(args); 
GenInterfaceBridge(args);

注册标签:看到LuaCallCSharp了吗?没错,在做生成类wrap文件操作的时候会做一次筛选,只生成那些注册了这个标签的结构。

以上提到的生成不同类型的函数,最终都会设置好参数然后走入核心函数GenOne:

红框标记部分意味着写入文件,自此生成部分结束。

wrap格式

xlua如何做到C#到wrap的映射的(它最起码得分明啥是代码啥是注释才对)?它什么时候开始做的映射?

由此引出了另一个C#文件:TemplateEngine.cs。这个文件做的最大的一个工作就是正则表达式匹配:

<text>直接当成字符串的内容

<code>可执行代码

<eval>用lua变量代替的内容

如下图诠释的:

wrap文件内容

有关类的模板文件参考LuaClassWrap.tpl.txt

之后会根据这个模板生成相关的类wrap文件(enum、接口等等同样如此)

如果想看到生成wrap的效果,可以点击xlua给我们的窗口:XLua->Generate Code。

仔细看源码可以发现,xlua的中央控制器生成的注册表是放在XLuaGenAutoRegister.cs中:

generate后可看到一系列wrap.cs:

这些文件以类似dictionary的管理形式在XLuaGenAutoRegister.cs中出现:

在这里直接贴出生成的LuaBehaviour.cs的wrap代码XluaToolLuaBehaviourWrap.cs:

简单可以理解成RegisterFunc(指针,位置,C#的函数名,翻译后的函数),我们随便挑一个函数看看:

注意,wrap文件只翻译public类型的function,protected和private因其私密性不被外界调用所以直接优化成不“翻译”了。看上图一段简单的return语句,实际上就是找到真实的函数所在栈空间,调用后返回相应值传回lua侧即可。如若是带参数的情况下则多添加几行lua参数的定位+翻译即可。

总结

说到这里,就已经很大程度地告诉大家lua侧能调用c#端的函数或者变量的原因了。

  • 32
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用XLua可以在Unity中实现Lua脚本的编写,同时也可以让Lua脚本与C#代码进行交互。 以下是基本的使用步骤: 1. 下载XLua插件并导入到Unity中。 2. 在Unity中创建一个新的Lua文件,编写Lua脚本代码。 3. 在C#代码中使用XLua的API来加载并运行Lua脚本,例如: ``` using XLua; public class LuaManager : MonoBehaviour { private LuaEnv luaEnv; void Awake() { luaEnv = new LuaEnv(); luaEnv.DoString("require 'main'"); // 加载并执行Lua脚本 } void Update() { luaEnv.Tick(); // 更新Lua环境 } void OnDestroy() { luaEnv.Dispose(); // 释放Lua环境 } } ``` 在上面的例子中,`Awake()`方法中创建了一个Lua环境,然后通过`DoString()`方法加载并执行了Lua脚本。`Update()`方法中每帧都调用了`Tick()`方法来更新Lua环境,`OnDestroy()`方法中释放了Lua环境。需要注意的是,在实际的项目中,可能需要更加复杂的逻辑和管理方式来处理Lua脚本的加载和运行。 4. 在Lua脚本中使用XLua提供的API来调用C#代码或者导出Lua模块,例如: ``` -- 导出一个Lua模块 local module = {} module.foo = function() print("Hello from Lua!") end return module -- 调用C#代码 local gameObject = CS.UnityEngine.GameObject("LuaObject") local transform = gameObject.transform transform.position = CS.UnityEngine.Vector3(1, 2, 3) ``` 在上面的例子中,导出了一个名为`module`的Lua模块,并定义了其中的一个函数`foo()`。同时,也调用了C#代码的API来创建了一个新的GameObject,并修改了它的Transform组件的位置。 XLua还提供了其他的功能,例如自定义导出规则、GC优化等。在使用XLua之前,建议先了解一些基本的Lua语法和C#与Lua交互的机制,以便更好地使用XLua
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值