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过程分析
Lua 热重载机制是程序开发中的一种实用特性,它允许程序员在程序运行时更新 Lua 脚本代码,而无需停止或重启程序。这种机制对于游戏开发、服务器维护和自动化脚本等场景尤其重要,因为它提高了调试和迭代效率。在 ...
通常,luaiconv是一个单独的`.lua`文件,你可以通过`require`函数将其引入到你的脚本中。例如: ```lua local iconv = require 'luaiconv' ``` 确保你的环境已经正确配置了Lua的路径,以便能成功加载luaiconv库。 2...
在Lua中,`require`函数是核心模块加载机制的关键部分,用于引入并执行其他模块代码,从而实现代码的复用和组织。在给定的标题“lua-require: Lua的轻量级副本基于理解和行为的require函数”中,我们了解到这是一个...
Lua提供了简单的错误处理机制,如try-catch风格的pcall函数,以及debug库用于跟踪和调试脚本执行。 **性能优化** 尽管Lua小巧,但在适当的设计下,其性能表现相当不错。通过合理利用元表、闭包和局部变量,以及...
Lua也具有异常处理机制,通过error函数抛出错误,通过pcall函数安全地执行函数,通过xpcall函数执行,并提供了一个自定义的错误处理函数。 Lua的设计者通过各种设计决策使其成为一种高效、灵活的编程语言,它广泛...
Lua没有内置的命名空间机制,但可以通过全局变量和表来模拟。模块通常被封装在表中,通过require函数导入。 6. **闭包与upvalue** Lua支持闭包,即一个函数可以记住并访问其词法作用域内的变量,即使该函数已经被...
这个资源包包含了“Lua中文教程”和“Lua源码赏析”两部分,旨在帮助初学者在短短两小时内快速掌握Lua编程基础,并通过源码分析深入理解其内部机制。 “Lua中文教程”可能涵盖以下内容: 1. **基础语法**:Lua的...
在Lua中,变量是动态类型的,无需预先声明。它支持五种基本数据类型:nil(无值)、boolean(布尔型)、number(数字)、string(字符串)和table(表)。表是Lua的通用数据结构,可以用于数组、集合、对象等多种...
在C++项目中集成Lua,通常需要使用一个名为"tolua++"或"luabind"的库,它们提供了将C++函数导出到Lua的机制。在这个实例中,C++工程可能已经包含了这样的库,并定义了一些可被Lua调用的函数。这些函数可以用来执行...
通过 require 函数,你可以加载并执行其他 Lua 脚本,实现模块化编程。另外,Lua 支持 C 语言扩展,允许开发者编写 C/C++ 代码来提供底层功能或优化性能关键部分。 Lua 的垃圾收集机制也是其一大亮点,它负责自动...
错误处理在Lua中通过异常机制实现,`error`函数抛出错误,`pcall`和`xpcall`函数可以捕获并处理错误。 最后,Lua的C接口允许与C语言或其他编译语言进行紧密集成,通过`luaL_newstate`创建Lua虚拟机,`luaL_openlibs...
4. **模块系统**:Lua的模块系统使得代码组织和重用变得简单,可以将相关功能封装在模块中,通过require函数导入使用。 5. **垃圾回收机制**:Lua自动管理内存,使用引用计数配合可达性分析的垃圾回收策略,开发者...
Lua支持轻量级的并发机制——协程,它们比线程更轻便,可以在单线程中实现协作式多任务。 9. **字符串处理**: Lua的字符串是不可变的,提供了丰富的字符串操作函数,如`string.sub`、`string.find`和`string....
4. **模块化编程**:通过require和package机制,Lua实现了模块化,使得代码组织更加有序,易于维护和重用。 5. **垃圾回收机制**:Lua采用自动垃圾回收策略,程序员无需手动管理内存,降低了出错的可能性。 6. **...
教程还会涵盖模块化编程,Lua通过require函数加载模块,并提供了package库来管理模块。理解如何组织和导入代码对于大型项目尤其重要。 错误处理和调试也是重要一环,Lua使用错误异常来处理程序运行中的错误,同时...
Lua的垃圾回收机制是其高效运行的关键之一。它采用引用计数加标记-清除的方式,自动管理内存,减少了程序员手动管理内存的负担,同时也降低了内存泄漏的风险。 第六部分:Lua的性能优化 尽管Lua是一种解释型语言,...
Lua是一种轻量级的脚本语言,主要用于嵌入到其他应用程序中以增加其功能。它的设计目标是简单、小巧、可扩展性强。由于其简洁的语法和高效的执行,Lua在游戏开发、网络编程、系统配置、数据库接口等多个领域都有广泛...
在LUA中,使用库通常通过`require`函数来加载。例如,如果要使用名为`mylib`的库,会在脚本中写入`require 'mylib'`。加载后,库中的函数和常量就可直接调用。对于LUA_FNEfne库,可能需要类似`require 'LUA_FNEfne'...
2. **类型转换**:Luanet提供了自动类型转换机制,使得Lua数据类型可以顺畅地转化为.NET类型,反之亦然。 3. **事件处理**:通过Luanet,Lua脚本可以注册和处理.NET事件,增加了交互的灵活性。 4. **异常处理**:...