Lua模块与包

Lua中的模块和包。

一个模块就是一些代码,这些代码可以通过函数require加载,然后创建和返回一个表。这个表就像是某种命名空间,其中定义的内容是模块中导出的东西,比如函数和常量。

函数require:

函数require尝试对模块的定义做最小的假设。对于该函数来说,一个模块可以是定义了一些变量的(比如函数或者包含函数的表)的代码。

require的加载机制

首先,函数require在表package.loaded中检查模块是否已被加载,如果模块已经被加载,函数require就返回相应的值,因此,一旦一个模块被加载过,后续的对于同一模块的所有require调用都将返回同一个值,而不会再运行任何代码。

如果模块尚未加载,那么函数require则搜索具有指定模块名的Lua文件(搜索路径由变量package.path指定)。如果函数require找到了相应的文件,那么就用函数loadfile将其进行加载,结果是一个我们称之为加载器的函数。

如果函数require找不到指定模块名的Lua文件,那么它就搜索相应名称的C标准库。如果找到了一个C标准库,则使用底层函数package.loadlib进行加载,这个底层函数会查找名为luaopen_modname的函数。在这种情况下,加载函数就是loadlib的执行结果,也就是一个被表示为Lua函数的C语言函数。

为了最终加载模块,函数require带着两个参数调用加载函数:模块名和加载函数所在的文件的名称。如果加载函数有返回值,那么函数require会返回这个值,然后将其保存在表package.loaded中,以便于将来在加载统一模块时返回相同的值。如果加载函数没有返回值且表中的package.loaded[@rep{modname}]为空,函数require就假设模块的返回值为true。如果没有这种补偿,那么后续调用函数require时将会重复加载模块。

编写模块的基本方法

在Lua语言中创建一个表,并将所有需要导出的函数放入其中,最后返回这个表。

另一种编写模块的方法是把所有的函数定义为局部变量,然后在最后构造返回的表。

字模块和包

Lua支持具有层次结构的模块名,通过点来分隔名称中的层次,例如一个名为mod.sub的模块是模块mod的一个子模块。一个包(package)是一棵由模块组成的完整的树,它是Lua语言用于发行程序的单位。