Lua热更原理以及加载规则

要实现Lua的热更新,首先要了解Lua的模块加载机制,热更新的核心就是替换package.loaded中的模块。

加载规则:

包管理库提供了从Lua中加载模块的基础库。只有一个导出函数直接放在全局环境中:require。所有其他的部分都导出在表package中。

require(modname)

查询全局缓存表package.loaded这个函数首先查找package.loaded表,检测modname是否被加载过。如果被加载过,require返回package.loaded[modname]中保存的值。否则,它试着为模块寻找加载器。

通过package.searchers查找加载器:require遵循package.searchers序列的指引来查找加载器。如果改变package.searchers中的序列,也会改变require如何查找一个模块的方式。

查找加载器:首先require查找package.preload[modname]。如果这里有一个值(必须是一个函数),则为加载器。否则require会使用Lua加载器去查找package.path的路径。如果查找失败,接着使用C加载器去查找package.cpath的路径。如果都失败了,再尝试一体化加载器(参见package.searchers详解)

加载器调用规则:每当找到一个加载器,require都用两个参数调用加载器:modname和一个在获取加载器过程中得到的参数(如果是通过查找文件得到的加载器,这个额外的参数即为文件名)。如果加载器返归非空值,require将这个值赋给package.loaded[modname]。如果加载器没能返回一个非空值用于赋给package.loaded[modname]require 会将true赋给 package.loaded[modname]。 无论加载器返回什么结果,require都会为package.loaded[modname]设置最终值。

报错:在加载或运行模块时有错误,或是无法为模块找到加载器,require都会抛出错误。

package.loaded

存储已经被加载的模块:require一个modname模块得到的结果不为假时,require返回这个存储的值。requirepackage.loader中获得的值仅仅是对那张表(模块)的引用,改变这个值并不会改变require使用的表(模块)。

package.preload

保存一些特殊模块的加载器:这里面的值仅仅是对那张表(模块)的引用,改变这个值并不会改变require使用的表(模块)。

package.path

Lua加载器的搜索路径:使用环境变量LUA_PATH_5_3LUA_PATH初始化。或者采用luaconf.h中的默认路径。环境变量中的所有";;"都会被替换为默认路径。

package.cpath

C加载器的搜索路径:使用环境变量LUA_CPATH_5_3LUA_CPATH初始化。或者采用luaconf.h中定义的默认路径。

package.searchers

require查找加载器的表:这个表内的每一项都是一个查找器函数。当加载一个模块时,require按次序调用这些查找器,传入modname作为唯一参数。此方法会返回一个函数(模块的加载器)和一个传给这个加载器的参数。或返回一个描述为什么没有找到这个模块的字符串或者nil

Lua共有四个查找器函数:

第一个查找器就是简单的在package.preload表中查找;

第二个查找器用于查找Lua库的加载库。它使用存储在package.path中的路径查找工作。查找过程和函数package.searchpath描述的一致;

第三个查找器用于查找C库的加载库。它使用存储在package.coath中的路径查找工作。查找过程和函数package.searchpath描述的一致;

第四个搜索器是一体化加载器,从C路径中查找指定模块的根名字。

除了第一个搜索器外,每个搜索器都会返回找到的模块的文件名。这和package.searchpath的返回值一样,第一个搜索器没有返回值。

package.searchpath(name, path[,sep[,,rep]])

在指定的path中搜索指定的name:路径是一个包含一些列分号分隔的模板构成的字符串。对于每个模板,都会用name替换其中的每个问号(前提是有问号)。且将其中的sep(点".")替换为rep(系统的目录分隔符"/")。谈候场时打开这个文件名。

例如,如果路径是字符串  "./?.lua;./?.lc;/usr/local/?/init.lua"  

搜索foo.a 这个名字将一次尝试打开文件./foo/a.lua      ./foo/a.lc   以及 /usr/local/foo/a/init.lua

返回第一个可以用读模式打开(并马上关闭该文件)的文件的名字。如果不存在这样的文件,返回nil加上错误的消息。(错误消息列出了所有尝试打开的文件名)
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值