lua table insert_【Lua运行时热重载②】重载Lua模块、替换函数

上篇说到检测Lua文件发生变化,这篇来讲怎么重载lua模块。 请配合github工程来看。

关于重载lua的功能在Hotfix.lua脚本上。这个脚本有三个函数,hotfixupdate_tableupdate_func


hotfix

function 

package.loaded

package.loaded是lua内部用于记录哪些模块被require的表,如果一个模块已经被require,那么下次再调用require就不会生效。 所以第一步就是把package.loaded记录的旧模块清空并重新require,然后使用pcall捕捉异常,如果出现错误,package.loaded仍然赋值旧模块,并返回。网上的很多博客也就停留在这一步了。 下一步就是更新旧模块,调用update_table,最后把package.loaded[filename] 指向旧模块。


update_table

function 

这个函数用于更新旧表,首先断言这两个参数的类型是不是table。 然后遍历表里面的元素,有三种情况:数据函数

  • 数据不做处理,让旧表保留旧的数据。
  • 函数,需要处理upvalue值,处理完之后,替换旧表里的旧函数
  • ,嵌套调用update_table

最后处理元表,把旧表的元表和新表的元表拿出来,嵌套调用update_table

为什么需要处理元表?

考虑下面的代码,这是我工程里BaseClass.lua的一段代码:

local 

当我对class_type表里添加元素时,实际上是往vtbl也就是class_type的元表进行操作。这样当我遍历class_type的时候,实际上是找不到我添加的元素的,因为这个元素在元表里。所以在更新表的时候,需要把新表和旧表的元表都取出来,然后再次调用update_table


update_func

function 

这个函数用于处理upvalue,什么是upvalue,就是一个函数使用了不在这个函数内的变量。如下代码:

local 

其中的count就是upvalue,当我更新函数的时候需要保留upvalue的值。

getupvalue、setupvalue

lua内部提供了这两个方法,我们只需要把旧函数的upvalue拿出来再赋值给新函数的upvalue就可以了。


到这里,看似热重载的功能已经完成了,但是还有一种情况没有考虑到,就是如果旧表的旧函数在其他地方已经被存了一份该怎么办? 这个时候就算你把旧表的旧函数更新为新函数了,实际上其他地方存的还是旧函数。 比如我工程里GameMain.lua的一段代码:

local 

当我更新旧表的函数后,playerMove.TestFunc() 的确是调用的新函数,但是GameMain.playerFunc() 还是旧函数。我的解决办法是在PlayerMove.lua增加OnReload这个函数,在这个函数对GameMain.playerFunc重新赋值,然后在hotfix方法里这么调用:

if 

OnReload代码如下:

local 

为什么需要分别考虑类和实例的情况?

我们都知道在lua里写面向对象,当我调用 [class].New() 时,实际上是生成了一个元表是[class]的实例。调用package.load[filename] 获得的是类的类型,并不是类的实例。那么我又需要调用类的实例的方法的时候怎么办?我的解决方法是类在生成一个实例时,用一个表去记录它都生成了哪些实例。同时设置成弱引用,这样当实例销毁并执行gc后,这个记录表也会自动取消对实例的引用。 在工程里的BaseClass.lua里面如下:

class_type
  • 其中class_type.instance用于记录生成的实例
  • __mode = "v",说明表里的value是弱引用
  • table.insert 用于往表插入元素

这就是为什么OnReload里面判断了一下是class还是instance的原因。


系列文章:

【Lua运行时热重载功能实现①】检测Lua文件发生变化

【Lua运行时热重载功能实现②】重载Lua模块、替换函数


CSDN博客:https://blog.csdn.net/j756915370

知乎专栏:https://zhuanlan.zhihu.com/c_1241442143220363264

Q群:891809847

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值