lua中的require机制
为了方便代码管理,通常会把lua代码分成不同的模块,然后在通过require函数把它们加载进来。
现在看看lua的require的处理流程。
1、require机制相关的数据和函数
package.path:保存加载外部模块(lua中"模块"和"文件"这两个概念的分界比较含糊,因为这个值在不同的时刻会扮演不同的角色)的搜索 路径,这种路径是"模板式的路径",它里面会包含可替代符号"?",这个符号会被替换,然后lua查找这个文件是否存在,如果存在就会调用其中特定的接 口。典型的值为:
"./?.lua;./?.lc;/usr/local/?/init.lua"
如果lua代码中调用:require("hello.world")
那么lua会依次查找:
./hello/world.lua ==>这里"hello.world"变成了"hello/world",并替换了模型"./?.lua"
./hello/world.lc
.....
(这种处理方式和python类似,只不过不需要__init__.py,也有调用python中的__init__.py)
package.path在虚拟机启动的时候设置,如果存在环境变量LUA_PATH,那么就用该环境变量作为
它的值,并把这个环境变量中的";;"替换为luaconf.h中定义的默认值,如果不存在该变量就直接使用
luaconf.h定义的默认值
package.cpath:作用和packag.path一样,但它是用于加载第三方c库的。它的初始值可以通过环境变量
LUA_CPATH来设置
package.loadlib(libname, func):相当与手工打开c库libname, 并导出函数func返回,loadlib其实是ll_loadlib
2.require的处理流程:
require(modelname)
require(在lua中它是ll_require函数)的查找顺序如下:
a.首先在package.loaded查找modelname,如果该模块已经存在,就直接返回它的值
b.在package.preload查找modelname, 如果preload存在,那么就把它作为loader,调用loader(L)
c.根据package.path的模式查找lua库modelname,这个库是通过module函数定义的,对于顶层的lua库,文件名和库名是一 样的而且不需要调用显式地在lua文件中调用module函数(在ll_require函数中可以看到处理方式),也就是说lua会根据lua文件直接完 成一个loader的初始化过程。
d.根据package.cpath查找c库,这个库是符合lua的一些规范的(export具有一定特征的函数接口),lua先已动态的方式加载该c库,然后在库中查找并调用相应名字的接口,例如:luaopen_hello_world
e.已第一个"."为分割,将模块名划分为:(main, sub)的形式,根据package.cpath查找main,如果存在,就加载该库并查询相应的接口:luaopen_main_sub,例如:先查找 hello库,并查询luaopen_hello_world接口
f.得到loder后,用modname作为唯一的参数调用该loader函数。当然参数是通过lua的栈传递的,所以loader的原型必须符合lua的规范:int LUA_FUNC(lua_State *L)
ll_require会将这个loader的返回值符给package.loaded[modelname],如果loader不返回值同时 package.loaded[modelname]不存在时, ll_require就会把package.loaded[modelname]设为true。最后ll_reuqire把package.loaded [modelname]返回给调用者。
3.module的处理流程
module(name, cb1, cb2, ...)
a.如果package.loaded[name]是一个table,那么就把这个table作为一个mod
b.如果全局变量name是一个table,就把这个全局变量作为一个mod
c.创建table:t = {[name]=package.loaded[name], ["_NAME"]=name, ["_M"]=t, ["_PACKAGE"]=*name*(删除了最后的".XXXX"部分)}. 如果name是一个以点分割的串,那么得到的mod类似这个样子:
hello.world==> {["hello"]={["world"]={XXXXXXX}}}
d.依次调用cbs:
cb1(mod), cb2(mod),...
e.将当前模块的环境设置为mod,同时把package.loaded[name] = mod
清楚了lua关于模块的处理,就比较容易理解写lua扩展的细节了^_^。
原文:http://blog.chinaunix.net/uid-552961-id-2736410.html
分享到:
相关推荐
lua搜索路径,require加载过程,c库loader过程分析
通过执行python脚本(jsonToLua.py)
用Lua语言写的一个配置文件转换工具,能够将csv配置文件转换为Lua“类文件”。支持的格式有数字、字符串、数字数组、字符数组和table等。内有详细使用说明。水平有限,如有Bug或者好的建议欢迎留言交流。
excel转lua工具,内含使用说明和demo文件。 工具方便开发。
c语言和lua语言的中文数字(语音数字)到阿拉伯数字相互转换函数
lua 热重载机制。
一个规范lua require路径的工具。 自动将识别lua require路径,自动修改不规范路径。 路径规范:1.使用全路径 2.使用“.”而非“/” 使用: 1.需要NodeJs环境 2.工具放在脚本根目录里,运行C_Lua_Require.bat。会...
主要介绍了Lua中的垃圾回收机制,自动的垃圾回收是Lua的重要特性之一,需要的朋友可以参考下
json转lua脚本,全自动转换 快速读取
lua json文件转换 数据编排 lua配置表转成 json配置表
ios版本将lua加密成luac
Excel转lua,c#,json等等,配置表工具,Excel转lua,c#,json等等,配置表工具
Excel配表转Lua脚本工具,采用QT编写,分析速度快,模式多,支持多文件,文件夹导入,批量导出
可以把json转换成lua文件放在工程里面 只需要指定文件读取位置 和 存放位置即可
用于lua的XML文件解析 LuaXML provides a minimal set of functions for the processing of XML data in Lua.
Lua源码剖析,Lua虚拟机的机制分析,硕士论文
需求Lua的轻量级副本基于理解和行为而需要功能。 仅在上运行该库就像需要它一样简单,它将以重复的方式覆盖当前环境的需求。 require ( ' require ' );
EXCEL配置转成lua的转表工具源代码。
lua解密工具微微有点老..也有不少不会编译的..本菜狗集成了一下.. 其实工具主要作用是处理unlua的中文问题.