在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Lua 5.1 加入模块管理机制module,类似于Java的packages、C++的namespaces,可以通过require用于加载模块,module用于创建模块。require加载一个自定义或者第三方的module,然后便得到了一个全局变量,表示一个table。 Lua 5.2 之后则去掉了module创建模块的函数,仅保留requir加载函数在全局环境 require函数创建模块在Lua中创建一个模块最简单的方法:创建一个table,并将所有需要导出的函数放入其中,最后返回这个table,相当于将导出的函数作为table的一个字段。 创建一个简单模块,代码如下:
调用模块require (modname) Loads the given module. The function starts by looking into the package.loaded table to determine whether modname is already loaded. If it is, then require returns the value stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module. To find a loader, require is guided by the package.loaders array.(package.loaders array:A table used by require to control how to load modules.) By changing this array, we can change how require looks for a module. The following explanation is based on the default configuration for package.loaders. First require queries package.preload[modname].(A table to store loaders for specific modules) If it has a value, this value (which should be a function) is the loader. Otherwise require searches for a Lua loader using the path stored in package.path. If that also fails, it searches for a C loader using the path stored in package.cpath. If that also fails, it tries an all-in-one loader (see package.loaders). Once a loader is found, require calls the loader with a single argument, modname. If the loader returns any value, require assigns the returned value to package.loaded[modname]. If the loader returns no value and has not assigned any value to package.loaded[modname], then require assigns true to this entry. In any case, require returns the final value of package.loaded[modname]. If there is any error loading or running the module, or if it cannot find any loader for the module, then require signals an error. require函数的调用形式为require "模块名" 加载给定的模块名modname,require函数首先会在表package.loaded中查看是否已经加载过,如果已经加载过,则会返回储存在package.loaded[modname]中的模块,否则,require函数将会尝试为此模块寻找一个加载器。 require函数将会被package.loader的数组引导来寻找适用于该模块的加载器,(package.loaders,是一个被require函数用来控制如何加载模块的表或者说数组)我们可以自己改变require函数寻找模块的方法,下面是package.loaders的默认配置的下的解释: 首先,require函数会查看package.preload[modname](用来储存特定模块加载器的表),如果有值(该值应是一个函数),则改值就是要找的加载器。否则,require函数将会通过储存在package.path中的路径来寻找一个Lua 加载器。如果也失败了,requier函数则会通过储存在package.cpath中的路径来寻找一个C 加载器。如果也失败了,require函数将会尝试使用一个package.loaders中的通用的加载器——all-in-one 加载器。 一旦找到加载器,require函数会传递一个单一的参数模块名modname到这个加载器,如果加载器有任何的返回值,require函数会将返回的值连同模块名modname会注册到表 package.loaded[modname]中。如果加载器没有返回值并且还没有任何值连同模块名modname会注册到表 package.loaded[modname]中,那么require函数将会注册 true 到该键值对的入口。任何情况下,require 函数都会返回表 package.loaded[modname]最终的值。 如果在加载或者运行该模块,亦或者完全没有找到该模块的加载器,则require函数会显示error。 将上方simpleMod.lua放置在当前目录的子目录Util下,调用代码:
输出结果: module函数简化module的创建
代码如下:
Lua5.1 & setfenv (f, table)Sets the environment to be used by the given function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling setfenv. setfenv returns the given function. As a special case, when f is 0 setfenv changes the environment of the running thread. In this case, setfenv returns no values. 当我们在创建模块或者访问同一个模块中的其它函数时,需要限定名称,就比如上面代码中的_Mod,为此,我们可以让模块的主程序块有一个独立的环境,这样不仅它的所有函数都可共享这个table,而且它的所有全局变量也都记录在这个table中。而模块所要做的就是将这个table赋予模块名和package.loaded。 这样,我们在调用同一个模块中的函数new时,也不用指定m了。在写自己的模块时,就省去了前缀;但是与此同时,当我们调用setfenv(1,m)函数之后,会将一个空table m作为环境,但是这样之后就无法访问前一个环境中全局变量了(例如setmetatablet之类的全局变量) 解决方法:
方法二:在调用setfenv(1,m)之前,使用局部变量将全局变量_G保存起来,代码如下:
方法三:在调用setfenv(1,m)之前,只将需要使用的全局变量保存起来,代码如下:
Lua5.1 & module(...)在Lua 5.1中,可以用module(...)的函数来代替以下代码:
由于在默认情况下,module不提供外部访问,必须在调用它之前,为需要访问的外部函数或模块声明适当的局部变量。然后Lua提供了一种更为方便的实现方式,即在调用module函数时,多传入一个package.seeall的参数,相当于 setmetatable(_Mod, {__index = _G}):
完整代码:
Lua5.2之后
Lua5.2之后,如果require引入使用module声明和定义的模块就会报错 REFhttp://www.lua.org/manual/5.1/manual.html#5.3 http://www.lua.org/manual/5.2/manual.html#pdf-package.searchers https://www.runoob.com/manual/lua53doc/manual.html#pdf-require http://www.ogeek.net/article/55818.htm https://moonbingbing.gitbooks.io/openresty-best-practices/lua/not_use_module.html https://www.cnblogs.com/zsb517/p/6822870.html |
请发表评论