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 》

时间: 2024-10-03 13:45:12

Chapter 15_1 require函数的相关文章

通过Include和Require函数实现代码重用

通过Include和Require函数实现代码重用     如果你做过各种大小的Web站点,一定会对重用代码段的重要性深有体会,不管是HTML还是PHP代码块.比如需要一年修改一次包含版权信息的页脚,而你有1000个Web页(就算是10个),手动操作则会让你痛苦不已. 通过PHP,你可以使用不同函数帮助你重用代码.具体用到的函数取决于你打算重用的内容. 主函数如下: include() and include_once() require() and require_once() include

Lua Require函数

转自:http://www.cppblog.com/cslover/archive/2013/12/21/204934.html Lua提供高级的require函数来加载运行库.粗略的说require和dofile完成同样的功能但有两点不同: 1. require会搜索目录加载文件 2. require会判断是否文件已经加载避免重复加载同一文件.由于上述特征,require在Lua中是加载库的更好的函数. require使用的路径和普通我们看到的路径还有些区别,我们一般见到的路径都是一个目录列表

luci 中require函数包含的路径

在 lua 脚本中常用的包含某个文件就是 require 函数. 例如: #!/usr/bin/lua                     // 表明使用的是lua脚本,像shell脚本一样 local http = require("socket.http") local json = require("luci.json") 有时候会遇到需要的文件查找不到的现象.例如: /usr/bin/lua: /usr/sbin/test:4: module 'luci

Chapter 3. 聚合函数

=====聚合函数===== sum 求和 select sum(列名)from 表名 count 计数 select count(*)from 表名 avg 平均数 select avg (列名)from 表名 max 最大值 select max(列名)from 表名 min最小值 select min(列名)from 表名 注: 1.聚合函数不统计空值 2.如果使用聚合函数的时没有group by分组,聚合函数默认把整个表中的数据当成一组来统计

PHP的require()函数可以在一行代码中多次读取

[[email protected]:~]$[[email protected]:~]$more tt.php m#!/opt/php/bin/php -q<?phpwhile(1){ sleep(2); $arr = require("bb.php");   ##可见即便是在while()循环中,php也是可以实时获取配置信息的.这里不会报重复require()的错误! echo $arr['aaa'],"\n"; } ?>[[email protec

lua加载函数require和dofile

Lua提供高级的require函数来加载运行库.粗略的说require和dofile完成同样的功能但有两点不同: 1. require会搜索目录加载文件 2. require会判断是否文件已经加载避免重复加载同一文件. 由于上述特征,require在Lua中是加载库的更好的函数. require使用的路径和普通我们看到的路径还有些区别,我们一般见到的路径都是一个目录列表.require的路径是一个模式列表,每一个模式指明一种由虚文件名(require的参数)转成实文件名的方法.更明确地说,每一个

require.js的简单使用

<script src="js/require.js"></script> <script src="js/require.js" data-main="js/main"></script> require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){ // some code here }); 使用require.

Javascript模块化编程(三):require.js的用法

作者: 阮一峰 日期: 2012年11月 7日 这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. <script src="1.js"></s

require.js的AMD规范详解

require.js使用简介 在web刚开始发展的蛮荒时代,一个页面中只需要加载一个或少量的js文件,不存在模块,也不存在冲突之类的问题,但随着web项目的发展,它越来越大,js文件动辄几十个,怎么加载就成为了一个问题,要为浏览器的性能考虑,还有各个js文件(模块)的依赖关系.require.js的出现就是为了解决这样的问题. 1.实现js文件的异步加载,避免网页失去响应. 2.管理模块之间的依赖性,便于代码的编写和维护. require.js加载 使用require.js的第一步,是先去官方网