Chapter 15_1 require函数
Lua提供了一个名为require的高层函数来加载模块,但这个函数只假设了关于模块的基本概念。
对于require而言,一个模块就是一段定义了一些值(函数或者包含函数的table)的代码。
为了加载一个模块,只需要简单调用require "modname" 。这个函数首先会查找package.loaded表,检查modname是否加载过。
如果加载过,require返回package.loaded[modname]中的值。
否则,它试着为模块寻找“加载器”。
首先require会搜寻Lua file 。如果找到lua文件,就调用loadfile加载,它的返回值是函数 即"加载器"。
如果找不到Lua文件,会寻找C库,如果找到,就调用package.loadlib加载,去寻找luaopen_modname标志函数。
每次找到加载器,require就用两个参数调用加载器:modname和一个在获取加载器过程中得到的参数(如果通过查找文件得到的加载器,这个额外参数就是文件名)。
如果加载器返回非空值,require将这个值赋给package.loaded[modname].否则也会为其设置true值,无论什么情况,require都会返回package.loaded[modname]的最终值。如果在加载或运行时有错误,或是无法为模块找到加载器,require都会抛出错误。
如果要用require加载模块两次,我们可以把package.loaded[modname]给擦除掉。
packag.loaded.[modname] = nil
有时需要讲一个模块改名,以避免名字冲突。比如同一个模块有不同版本的情况。对于一个lua文件来说,改掉名字就可以了。
但是对于一个C程序库,我们就不能编辑其中的luaopen_*函数的名称了。为此,require用到了一个小技巧:
如果一个模块中包含了连字符 " - " ,require就会用连字符后的内容来创建luaopen_*函数名。
比如一个模块名为module-hello,require就会认为它的open函数是luaopen_hello,并不是luaopen_a-b。
因为在C语法中,连字符作为函数名是非法的。
因此,如果我们需要用两个同名的mod模块,可以把其中一个重新命名为mod-hello,一个命名为mod-world。
当调用
m1 = require "mod-hello"
require函数会找到这个mod-hello文件,并且在这个文件里,去找luaopen_mod函数。
注意:Lua5.2与Lua5.3这里是完全相反:5.2移除"-"之前的,5.3移除“-”之后的。
Lua5.3的版本,如果遇到a.b.c-v2.1的模块名,函数名就是luaopen_a_b_c。横线后的都忽略掉。
路径搜索
当搜索一个Lua文件的时候,rquire用的的路径是一系列样板(templates),其中的每一个指定了模块的文件名。
在每个路径样板中都包含了一个可选的'?'符号,require会用模块名去替代这个问号(如果有的话),再去检查这个文件是否存在。
如果该样板没有,就从下一个样板继续寻找。这些路径样板被";"一个个隔开:
?;?.lua;c:\Windows\?;/usr/local/lua/?/?.lua
require "mod" 语句会寻找下面的文件:
mod
mod.lua
c:\Windows\mod
/usr/loacl/lua/mod/mod.lua
require只处理 ";" 和 "?" 符号,其他符合则是路径自己定义的。
require找lua文件时路径变量是package.path。Lua一开始会用LUA_PATH_5_3环境变量去初始化它。
如果没有定义这个环境变量,就会用LUA_PATH。如果两个都没有定义,Lua会用luaconf.h里的默认路径。
环境变量中出现的所有“;;”都会被替换成默认路径。
比如你把LUA_PATH_5_3设置为“mydir/?.lua;;”,最后的路径会是"mydir/?.lua"之后跟着的是默认路径。
require寻找C库的方法也是一样的,但是变量变成了package.cpath。初始化的时候使用的是LUA_CPATH_5_3和LUA_CPATH。
在UNIX中是这样的:
./?.so;/usr/local/lib/lua/5.3/?.so
package.searchpath函数包含了所有搜寻库的规则,它接收一个模块名和一个路径。
路径是一系列以分号分隔的模板构成的字符串,在其中搜索指定的name。
返回第一个可以用读模式打开(并马上关闭该文件)的文件的名字。如果不存在这样的文件,即返回nil加上错误消息。
该错误消息列出所有尝试打开的文件名。
搜寻器
用于require控制如何加载模块的表--package.searchers
表内的每一项都是一个查找器函数,当查找一个模块时,require按照次序调用这些查找器,并传入唯一的模块名参数。
成功则返回另一个函数(模块的加载器)和一个加载器需要的参数。nil则表示错误。
Lua用四个查找器函数初始化该表:
1> 在package.preload表中查找加载器,没有返回值。
2> 查找Lua库的加载库,用存储在package.path中的路径来查找
3> 查找C库的加载库,使用存储在package.cpath中的路径。
4> 一体化加载器,从C路径中查找指定模块的根名字。例如“a.b.c”;它将查找a这个库。如果找到就会在里面找子模块的加载函数,就是找luaopen_a_b_c。
比如查找 “hello.core” 模块,就是寻找hello库的core子模块。对应的函数就是luaopen_hello_core。
这样可以把若干C子模块打包进单个库。每个子模块都可以有原本的加载函数名。
以上内容来自:《Lua程序设计第二版》和《Programming in Lua third edition 》
Chapter 15_1 require函数的更多相关文章
- 【前端】require函数实现原理
// require函数实现原理: function require(modulePath) { var regExp = /\w+$/g; var moduleName = regExp.exec( ...
- Lua Require函数
转自:http://www.cppblog.com/cslover/archive/2013/12/21/204934.html Lua提供高级的require函数来加载运行库.粗略的说require ...
- WAP调用微信支付https://pay.weixin.qq.com/wiki/doc/api/wap.php?chapter=15_1
公司做的一个购物网站 之前微信版的网站要搬在webView上 可是微信支付是个问题 , 在外部浏览器怎么都发不起微信请求 , 原因是因为页面调用的微信浏览器自带JSAPI 在外部浏览器无法调用,但 ...
- luci 中require函数包含的路径
在 lua 脚本中常用的包含某个文件就是 require 函数. 例如: #!/usr/bin/lua // 表明使用的是lua脚本,像shell脚本一样 lo ...
- JS中require函数的警告提示
在JS中常常使用require函数来引入文件或者路径,不过在使用时需要注意一点,它的参数必须是一串完整的字符串常量或者是由字符常量与变量拼接. (一)require函数的参数为一个变量,如下图所示: ...
- Chapter 21_2 模式匹配函数
基础函数比较简单,就是几个普通的函数string.byte.string.char.string.rep.string.sub.string.format还有大小写转换函数upper和lower. 接 ...
- PHP的require()函数可以在一行代码中多次读取
[root@NJ232:~]$[root@NJ232:~]$more tt.php m#!/opt/php/bin/php -q<?phpwhile(1){ sleep(2); $arr = r ...
- Chapter 21_1 字符串函数
接下来开始接触Lua强大的字符串处理能功能——字符串库. 原始的Lua解释器操作字符串的能力很有限,真正强大的能力还是来自字符串库. 它所有的函数都在模块string中.它还为strings设置了一个 ...
- Chapter 17_2 备忘录函数
一项通用的编程技术:用空间换时间. 例如有一种做法就可以提高一些函数的运行速度,记录下函数计算的结果,当再次调用该函数时,便可以复用之前的结果. 比如,一个普通服务器,在它收到请求中包含Lua代码,会 ...
随机推荐
- android 控件自定义样式
一.按钮(Button) 方式1.存在.9图片或图片时 可在drawable文件夹下新建xml文件style_button_one.xml,代码如下 <?xml version=" ...
- 给RelativeLayout设置背景,无效果bug解决
drawable文件夹下面 tomyshop_selector.xml文件 <?xml version="1.0" encoding="utf-8"?&g ...
- C#基础、基础知识点(新人自我总结,开启java学习之路)
从2016年12月29开班,开课到现在C#基础已经算是简答的学习了一点,一个为期两周的课程,或多或少对现在学的Java有着一定的帮助吧,我们先从软件入门来接触c#这门语言: 一.软件开发中的常用术语: ...
- GraphLab介绍[转]
GraphLab介绍 原文链接:http://blog.jasonding.top/2015/06/08/Machine%20Learning/%E5%BC%80%E6%BA%90%E5%9B%BE% ...
- jquery中的serialize
jquery中的serialize对serializeArray进行了封装,serializeArray源码中定义将disabled的过滤掉,所以提交后值为null 解决方式是:在提交的时候,讲dis ...
- 阿里云ECS-Nginx阿里云客户端IP日志记录
#前端有SLB服务,记录客户端真实IP信息 log_format main 'realip:$http_x_forwarded_for slbip:$remote_addr-$remote_user ...
- jQuery的9中构造函数
// 接受一个字符串,其中包含了用于匹配元素集合的 CSS 选择器 jQuery([selector,[context]]) // 传入单个 DOM jQuery(element) // 传入 DOM ...
- 组合,关联,聚合的区别(转自http://jimmyleeee.blog.163.com/blog/static/9309618200932014422932/)
类间关系 在类图中,除了需要描述单独的类的名称.属性和操作外,我们还需要描述类之间的联系,因为没有类是单独存在的,它们通常需要和别的类协作,创造比单独工作更大的语义.在UML类图中,关系用类框之间的连 ...
- datables的基本操作
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- NameCheap域名注册商的几个特点介绍
作为站长,我们拥有选择3-5家域名注册商,把自己的域名放置在不同的平台也是应该的,因为不同的注册商都有不同的值得我们选择的理由.作为已经使用namecheap注册商超过5年,拥有数百个域名的我来说,分 ...