ToLua源码分析:启动流程

说明

临时工先顶上来,回头整理施工。发现流水账叙述比较无趣和难懂,后面考虑更换形式。
ToLua版本1.0.6。
第一篇启动不深入过多细节,后面对特性进行深入解析。
部分代码进行了抽取,以c#、c、lua形式混写。实际以源码为准。
系列前置关卡:

  • Lua语言。
  • Unity使用经验。
  • Lua与宿主语言交互经验。
  • ToLua接入和使用经验。
  • tolua Unity工程和tolua_runtime源码(不给下载链接,搜索和查阅资料是一项基本功)。

      ToLua基于LuaInterface,LuaInterface是一个实现lua和微软.Net平台的CLR混合编程的开源库,使得lua脚本可以实例化CLR对象,访问属性,调用方法甚至使用lua函数来处理事件。ToLua保留了LuaInterface基本形式,重写或移除了部分内容,使代码更加简洁,提供了对Unity的支持、拓展了lua5.1.4源码。而最大的改进在于,LuaInterface中lua访问CLR需要运行时反射,对于游戏应用来说效率不够理想,ToLua则提供了一套中间层导出工具,对于需要访问的CLR、Unity及自定义类预生成wrap文件,lua访问时只访问wrap文件,wrap文件接收lua传递来的参数,进行类型(值、对象、委托)转换,再调用真正工作的CLR对象和函数,最后将返回值返回给lua,有效地提高了效率。

核心功能及文件

  • 提供Lua-c#值类型、对象类型转化操作交互层。(ObjectTranslator.cs、LuaFunction.cs、LuaTable.cs、ToLua.cs等)
  • 提供Lua虚拟机创建、启动、销毁,Require、DoFile、DoString、Traceback等相关支持。(LuaState.cs、LuaStatic.cs)
  • 提供导出工具,利用c#反射,对指定的c#类生成对应的wrap文件,启动后将所有wrap文件注册到lua虚拟机中。(ToLuaMenu.cs、ToLuaExport.cs、ToLuaTree.cs、LuaBinder.cs、CustomSetting.cs等)
  • 提供c#对象和lua userdata对应关系,使该userdata能访问对应c#对象属性,调用对应c#对象函数。lua支持一定的面向对象(类、继承)。管理这些对象的内存分配与生命周期、GC。(LuaState.cs)
  • 提供支持功能Lua Coroutine、反射等,Lua层重写部分性能有问题对象如Vector系列。(Vector3.lua等)

启动代码

  ToLua启动只需要三句代码即可。但里面实际经历了一段漫长的日夜。

void Start() 
{
    lua = new LuaState();  // 启动1:创建tolua提供的LuaState对象。              
    lua.Start();           // 启动2:虚拟机初始化。
    LuaBinder.Bind(lua);   // 启动3:Lua-c#中间层wrap文件们分别向虚拟机注册自己。
}

启动1 :lua new LuaState()

  实例化LuaState对象。类的成员属性按子类基类的顺序初始化,类的构造函数按基类子类顺序执行。
LuaState继承自LuaStatePtr,该类包含一个System.IntPtr L指针,即lua虚拟机栈,并提供了一系列LuaDLL API的封装,可以认为是LuaDLL的升级版。而成员属性中比较重要的有ObjectTranslatorLuaReflection,暂时我们只用关注ObjectTranslator。

// LuaState.cs
public class LuaState : LuaStatePtr, IDisposable {
    public ObjectTranslator translator = new ObjectTranslator();
    public LuaReflection reflection = new LuaReflection();

    public LuaState() 
    {
        ...
    }
}

启动1.1 : ObjectTranslator

  ObjectTranslator主要用于缓存lua需要访问的c# object对象。提供了对象池以及添加、查询、删除对象方法。管理对象的生命周期。LuaObjectPool对象池包含了一个PoolNode对象列表进行循环复用,PoolNode对象包含对真正object的引用,以及一个当前空闲索引的链表,其策略类似于lua_ref。

public class ObjectTranslator {

    //gc打印标志
    public bool LogGC { get; set; } 

    // 静态单例
    private static ObjectTranslator _translator = null;  

    // object对象在对象池中的索引。
    public readonly Dictionary<object, int> objectsBackMap = 
             new Dictionary<object, int>(new CompareObject());   

    // object对象池。
    public readonly LuaObjectPool objects = new LuaObjectPool();     

     // 延迟gc列表,目前只在GameObject.Destroy(go, float t)传递了参数t时使用。
    private List<DelayGC> gcList = new List<DelayGC>();

    public ObjectTranslator()
    {
        // 是否在RemoveObject时,打印信息
        LogGC = false;  
        // 单例
        _translator = this;  
    }

    // 获得单例
    public static ObjectTranslator Get(IntPtr L) {
        return _translator;
    }

    // 缓存一个object,返回在LuaObjectPool中的索引。
    public int AddObject(object obj) {...}
  • 21
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
tolua是一种用于Lua脚本与C++代码互相调用的工具。热更新是指在应用程序运行过程中对部分代码或资源进行更新而无需重启应用程序的一种技术。 基于tolua的热更新流程一般包括以下几个步骤: 1. 准备Lua脚本和相关资源:首先,需要准备好新的Lua脚本和相关资源文件,这些文件包括更新后的代码逻辑、配置文件、图片、音频等。 2. 下载更新内容:接下来,应用程序需要从服务器或其他渠道下载更新的内容。可以通过HTTP或FTP等网络协议下载文件,也可以使用其他的下载方式。 3. 替换旧的Lua脚本和资源:下载完成后,将新的Lua脚本和资源替换掉原有的文件。这一步可以根据具体的应用程序结构和资源管理方式来确定。 4. 热更新处理:在应用程序运行时,需要动态加载更新后的Lua脚本并重新加载相关资源。这可以通过tolua提供的接口来实现,将新的代码逻辑注入到应用程序中。 5. 更新后的逻辑生效:更新后的Lua脚本和资源生效后,应用程序会按照新的逻辑运行,实现热更新的效果。这样就可以在不重启应用程序的情况下完成代码或资源的更新。 总的来说,基于tolua的热更新流程可以通过下载更新内容、替换旧的Lua脚本和资源、热更新处理和更新后的逻辑生效等步骤来完成。通过这种方式,可以实现应用程序的部分代码或资源的更新,提升开发效率和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值