当我们需要在脚本中引入第三方库或者脚本文件时,比如 socket.dll和redis.lua文件,通常我们只需要执行require("socket") 和 require("redis")即可,但是require是怎么找到这2个文件呢?
require会调用四个查找器,分别如下:
第一个查找器就是简单的在package.preload表中查找加载器。
第二个查找器用于查找 Lua 库的加载库,它使用储存在package.path中的路径来做查找工作。
第三个查找器用于查找 C 库的加载库,它使用储存在package.cpath中的路径来做查找工作。
第四个搜索器是一体化加载器,它从 C 路径中查找指定模块的根名字。
但是默认情况下package.path和package.cpath存储的路径通常是lua执行程序所在路径,且不一定能够找到socket.dll和redis.lua文件。除非你直接将这2个文件放到lua执行程序目录中。所以为了方便管理,这个时候我们就需要将这2个文件所在的路径添加到package.path和package.cpath中。
假如这2个文件所在的路径是:E:/test/myscript/
1. 需要require的是lua脚本时,需要把路径拼接到package.path中。
package.path = "E:/test/myscript/?.lua;"..package.path
2. 需要require的是dll/so等动态库时,需要把路径拼接到package.cpath中。
package.cpath = "E:/test/myscript/?.dll;"..package.cpath
如果有多个路径则都要添加进去,但是每个路径需要使用分号隔开,使用问号代表搜索文件的通配符。
如果在E:/test/myscript/路径下有多个层级的目录,比如E:/test/myscript/factory/ E:/test/myscript/factory/car E:/test/myscript/human。而且每个目录下又有多个lua脚本,那么为了方便统一管理,可以在E:/test/myscript/目录新建一个ScriptLoader.lua文件,这样我们只需要在脚本最开始运行的地方把路径E:/test/myscript/添加到package.path中并require("ScriptLoader")即可,然后ScriptLoader.lua的内容如下:
--ScriptLoader.lua文件
do
local currentDir = debug.getinfo(1,"S").source
currentDir = string.sub(currentDir,2) --filter out '@'
currentDir = string.reverse(currentDir)
local pos = string.find(currentDir,"/",1,true)
if nil==pos then pos = string.find(currentDir,"\\",1,true) end
currentDir = string.sub(currentDir,pos)
currentDir = string.reverse(currentDir).."?.lua"
pos = string.find(package.path, currentDir, 1, true)
if nil==pos then
package.path = currentDir .. ";" .. package.path
end
end
require("factory.AA")
require("factory.BB")
require("factory.car.CC")
require("factory.car.DD")
require("human.EE")
require("human.FF")
顶层父目录添加到package.path后,剩下的require时通过.点的方式来指定子目录。所以上述的:
require("factory.AA") 表示的是加载E:/test/myscript/目录下的factory/AA.lua文件
require("factory.car.CC") 表示的是加载E:/test/myscript/目录下的factory/car/CC.lua文件
require("human.EE") 表示的是加载E:/test/myscript/目录下的human/EE.lua文件