require内部流程

来源:互联网 发布:ios socket编程 demo 编辑:程序博客网 时间:2024/05/16 21:53

记录对lua require时内部的执行流程和自定义加载器方法

更详细的说明参考手册:http://cloudwu.github.io/lua53doc/manual.html#pdf-require

当调用require(modname)时,lua执行相当于如下流程

local function myrequire(modname)local val = package.loaded[modname] -- loaded里已有,直接返回if package.loaded[modname] thenreturn valendfor _,loader in ipairs(package.searchers) do -- 遍历searchers查找加载器local func,msg = loader(modname) -- 传入modname调用加载器local t = type(func)if t == "function" then -- 加载器返回的是函数,表示找到local ret = func(modname,msg) -- 用modname和加载器返回的另一个参数调用funcif ret == nil thenret = trueendpackage.loaded[modname] = retbreakelseif t == "string" then -- 返回的是字符串,表示找不到的提示信息,输出print(func)else -- 返回的其它值都表示找不到,不提示endendend

package.searchers里存的是加载器,加载器以modname传入调用,其返回值有

1.函数(func)+参数(msg),表示找到,参数可以没有,以func(modname,msg)调用,其返回值存到package.loaded里

2.字符串,表求找不到,输出字符串表示找不到的提示信息

3.nil,表示找不到,没有提示


默认情况下searchers里有4个加载器

1.preload:查找package.preload[modname]值,存在且为函数,以modname调用该函数,返回值放loaded里

2.lua:查找package.path,找到文件(lua,luac...),以文件内容生成函数,并以modname,文件名调用,返回值放loaded里

3.c:查找package.cpath,打到文件(dll,so,...),查找luaopen_modname函数,调用之,luaopen_modname要把值压栈,该值会放loaded里

4.all-in-one:跟c加载器差不多,只是找到luaopen函数名不一样,如require("a.b.c")会加载a.dll文件然后找luaopen_a_b_c函数,主要用于方便组织代码包


要加入自定义的加载器,可以像如下的写法

local track = {}
function track.testrequire()local function func(...) -- 加载函数print("func",...)return 1 -- 返回值会放到loaded里endlocal function loader(...) -- 加载器print("loader",...)return func,"abc" -- 找到,func+msg,msg可以不用-- return "\n\terror not found!!!!!" -- 找不到,提示-- return nil -- 找不到,不提示endtable.insert(package.searchers,2,loader)require("mylib")print(package.loaded["mylib"])endtrack.testrequire()
输出

loader mylib
func mylib abc
1

quick-cocos2dx-3.3为了跨平台(win,mac,andorid,ios...),也在preload加载器后插入了自已的加载器cocos2dx_lua_loader,内部调用了FileUtils的一些读取文件接口。

0 0
原创粉丝点击