lua require机制

path

package.pathpackage.cpath 中, 保存了lua的文件路径模版, 在执行require时, 会将参数带入到模板中查找加载文件

文件加载策略
  1. 查找package.loaded表, 检测文件是否已经被加载, 如果已经被加载, 则直接返回已被加载到内存中的数据
  2. package.searchers中总共有4个加载器, 分别是 预加载器 lua加载器 c加载器 一体化加载器, require也按照顺序来执行加载器。找到了就成功返回,没有就继续查找
  3. 加载文件的过程中, 会将路径模板中的?替换为文件名, 例如, 模板为C:\lua-5.3.6\bin\lua\?.lua;C:\lua-5.3.6\bin\lua\?\init.lua;C:\lua-5.3.6\bin\?.lua;C:\lua-5.3.6\bin\?\init.lua;C:\lua-5.3.6\bin\..\share\lua\5.3\?.lua;C:\lua-5.3.6\bin\..\share\lua\5.3\?\init.lua;.\?.lua;.\?\init.lua;, 在require("main")时, 会依次尝试打开C:\lua-5.3.6\bin\lua\main.lua;C:\lua-5.3.6\bin\lua\main\init.lua;C:\lua-5.3.6\bin\main.lua;C:\lua-5.3.6\bin\main\init.lua;C:\lua-5.3.6\bin\..\share\lua\5.3\main.lua;C:\lua-5.3.6\bin\..\share\lua\5.3\main\init.lua;.\main.lua;.\main\init.lua;, 加载动态库文件时也是同理
加载成功后处理

加载文件成功后, package.loaded中会记录该模块, 下次require时, 就会直接使用loaded中的数据

重写require实现lua环境修改功能

在require时, 如果需要修改_ENV, 可以通过重写require函数来实现, 具体实现细节如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
local require = function (name, mode, env)
mode = mode or "bt"
env = env or _ENV
local filename, error = package.searchpath(name, package.path)
assert(filename, error)
local func, err = loadfile(filename, mode, env)
assert(func, string.format("loadfile [%s] failed", filename))
return func()
end
function new_env(path)
local env = {
assert = assert,
package = package,
loadfile = loadfile,
require = _require,
}
local before = _ENV
_ENV = env
module = require(path)
module.xxx()
_ENV = before
end