lua-模块和包

lua-模块和包(上)

Lua语言从5.1开始为模块和包定义了一系列规则。
从用户观点来看,一个模块(modle)就是一些代码(要么是Lua编写的,要么是C语言编写的),这些代码可以通过函数requie加载,然后创建和返回一个表。这个表就像是某种命名空间,其中定义的内容是模块中导出的东西,例如函数和常量
例如,所有的标准库都是模块

local m = require "math"
print(m.sin(3.14))
--> 

其中,用户调用模块函数的几种方法如下
1:用户可以为模块设置一个局部名称

local m = require "mod"
m.foo()

2:可以为个别函数提供不同的名称

local m = require "mod"
local f = m.foo
f()

3:引入特定的函数

local f = require "mod".foo  -- (require("mod")).foo
f()

函数require

函数require常用的方法(简单的调用这个函数,并传入模块的名作为参数):

local m = require ('math')
local m = require 'math'
local m = require (modname)

require加载的模块的过程

函数require主要目的就是避免重复加载模块,模块在任何情况下只是加载一次,至于如何处理冲突,取决于模块自己。

1:函数require会在package.loaded中检查模块是否已经被加载过,如果模块已经被加载,函数require就返回对应的值(即后续对同一模块的调用都是返回一个值,不再运行任何代码,require)。
2:若模块没被加载,则搜索具有指定模块的名的lua文件(搜索路径由packpath指定)。找到相应的文件后通过loadfile将其加载,结果是一个加载器(loader)的函数(加载器就是一个被调用时加载模块的函数)
3:如果函数require找不到模块名的lua文件,那么久搜索相应的C标准库,如果找到了一个C标准库,则使用底层的package.lib加载。

注意:不管模块还是C标准库中找到,函数require此时都是具有加载它的加载函数,加载函数的返回值被保存在package.load中,以便加载同一模块时返回相同值
因此,强制加载多次同一模块时候可以先将模块从package.load中删除:

package.load.modename = nil

模块重命名

通常情况下,我们通过模块本来的名称来使用它,但有时我们也需要将模块改名来避免命名冲突。
其中典型的情况就是,出于测试的目的而需要加载同一模块的不同版本
分为两种情况:
1:Lua语言模块
通常修改的是.lua文件文件名,不过我们无法修改C标准库的二进制代码中luaopen_*函数的名称,因此函数require可以运用一个连字符技巧:如果一个函数中包含连字符,那么函数require就使用连字符之前的内容来创建luaopen_*函数的名称,例如mod-v3.4,那么require认为该模块加载的是luaopen_mod模块的名为mod-v3.4
等价说法就是如果使用两个名字均为mod的模块(或者相同模块不同版本),那么对其中一个进行重命名,如mod-v1。当调用m1 = require "mod-v1"时,函数require会找到改名后的文件并将其中原名为luaopen_mod的函数作为加载函数

搜索路径

在搜索一个lua文件时,函数require使用的路径和典型的路径不同。IOS C(lua依赖的抽象平台)没有目录的概念,函数require使用的路径是一组模板,其中每项都指定了将模块名(函数require的参数)转换成为文件名的方式。更准确的讲路径中每个模板都是一个包含可选问号的文件名。函数require会用模块名来替代每个问号,然后检查是否存在文件;如果不存在则尝试下一个模板。
例如:

?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua

在使用这个路径时候会尝试打开一下lua文件

sql
sql.lua
c:\windows\sql
/usr/loacl/lua/sql/sql.lua

函数require只处理分号(分隔符)和问号,所有其他部分则由路径自己定义。
函数require用于搜索lua文件的路径变量是变量package.path的当前值。当package模块被初始化之后,它就把变量package.path设置成为环境变量LUA_PATH_5_3的值。如果这个环境变量没有被定义,那么lua语言将会尝试另一个环境变量Lua_PATH。如果这两个环境都没有被定义,那么lua语言则使用一个编译时定义的默认路径。
注意:搜索C标准库的路径逻辑与此相同,只不过C标准库的路径来自变量package.cpath而不是package,path。定义的拓展名的路径POSIX(xxx.so)Windows(xxx.dll)
函数package.searchpath中实现了搜索库的所有规则,该函数参数包含了模块名和路径

path = ".\\?.dll;C:\\Program Files\\Python35\\DLLs\\?.dll"
print(package.searchpath("tcl86t",path))  -->C:\Program Files\Python35\DLLs\tcl86t.dll

搜索器

搜索lua文件和C标准库的方式更加通用的搜索器(searcher)两个实例,一个搜索器是以模块名为参数,以对应模块的加载器或nil为返回值得简单函数
预加载(preload)搜索器使得我们能够为要加载模块定义任意的加载函数。预加载搜索器通过使用一个名为package.preload的表来映射模块名称和加载函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值