ulua 路径小记 以及 lua require 机制整理
ulua 路径小记
在学习ulua时,require模块的根路径可以为项目的Lua文件夹或者ToLua文件夹(Editor下),但是在package.path和package.cpath中并没有看到当前项目的路径,那require是如何找到Lua和ToLua文件夹的路径的呢?
- ulua在初始化
LuaState时,会先解析package.path, 并将其存入LuaFileUtils的SearchPaths中(LuaState.cs line:603),并将Lua和ToLua的目录添加其中(LuaState.cs line:187)。 - 在LuaState的构造函数中,会调用
ToLua.OpenLib(T),该方法定义了一下特殊方法,可以在lua中使用,如typeof等。 OpenLib方法会在package.loaders数组中,再添加一个loader,并且将其放到数组的第二个位置。(ToLua.cs line:192)注:Lua require模块时,会依次调用package.loader中的方法,找到则返回- loader的作用就是检测传入的文件名(module名),是否在
LuaFileUtils的SearchPaths,如果存在就读取文件,若不存在则返回空(LuaFileUitls.cs line:170)
Lua require 相关整理(基于lua 5.1)
摘自http://cloudwu.github.io/lua53doc/manual.html#6.3
根据lua5.1 手册做了部分修改
package.preload
为指定的模块,设置loader,在require模块时,先去查询这张表,如果有值,则使用preload中的loader(可以用于修改特殊模块的加载策略)
package.path
这个路径被 require 在 Lua 加载器中做搜索时用到。
在启动时,Lua 用环境变量 LUA_PATH来初始化这个变量。 或采用 luaconf.h 中的默认路径。 环境变量中出现的所有 ";;" 都会被替换成默认路径。
package.cpath
这个路径被 require 在 C 加载器中做搜索时用到。
Lua 用和初始化 Lua 路径 package.path 相同的方式初始化 C 路径 package.cpath 。 它会使用环境变量LUA_CPATH初始化。 要么就采用 luaconf.h 中定义的默认路径。
package.loaders(Lua5.3中, 改名为searchers)
用于 require控制如何加载模块的表。
这张表内的每一项都是一个 查找器函数。 当查找一个模块时, require 按次序调用这些查找器, 并传入模块名(require的参数)作为唯一的一个参数。 此函数可以返回另一个函数(模块的 加载器)加上另一个将传递给这个加载器的参数。 或是返回一个描述为何没有找到这个模块的字符串 (或是返回 nil 什么也不想说)。
Lua 用四个查找器函数初始化这张表。
第一个查找器就是简单的在 package.preload 表中查找加载器。
第二个查找器用于查找 Lua 库的加载库。 它使用储存在 package.path 中的路径来做查找工作。路径是一个包含有一系列以分号分割的 模板 构成的字符串。 对于每个模板,都会用 name 替换其中的每个问号(如果有的话)。 且将其中的 点替换为系统的目录分割符(如 Unix中的"/")。 然后尝试打开这个文件名。
例如,如果路径是字符串
"./?.lua;./?.lc;/usr/local/?/init.lua"
搜索 foo.a 这个名字将 依次尝试打开文件 ./foo/a.lua , ./foo/a.lc ,以及 /usr/local/foo/a/init.lua。
第三个查找器用于查找 C 库的加载库。 它使用储存在 package.cpath中的路径来做查找工作。 例如,如果 C 路径是这样一个字符串
"./?.so;./?.dll;/usr/local/?/init.so"
查找器查找模块 foo 会依次尝试打开文件 ./foo.so,./foo.dll, 以及 /usr/local/foo/init.so。 一旦它找到一个 C 库, 查找器首先使用动态链接机制连接该库。 然后尝试在该库中找到可以用作加载器的 C 函数。 这个 C 函数的名字是 "luaopen_" 紧接模块名的字符串, 其中字符串中所有的下划线都会被替换成点。 此外,如果模块名中有横线, 横线后面的部分(包括横线)都被去掉。 例如,如果模块名为 a.b.c-v2.1, 函数名就是luaopen_a_b_c。
第四个搜索器是 _一体化加载器_。 它从 C 路径中查找指定模块的根名字。 例如,当请求 a.b.c 时, 它将查找 a 这个 C 库。 如果找得到,它会在里面找子模块的加载函数。 在我们的例子中,就是找 luaopen_a_b_c。 利用这个机制,可以把若干 C 子模块打包进单个库。 每个子模块都可以有原本的加载函数名。
require(modname)
加载一个模块。 这个函数首先查找 package.loaded表, 检测 modname 是否被加载过。 如果被加载过,require 返回 package.loaded[modname] 中保存的值。(防止重复加载) 否则,它试着为模块寻找 加载器 。
首先 require 查找 package.preload[modname] 。 如果这里有一个值,这个值(必须是一个函数)就是那个加载器。 否则 require 使用 Lua 加载器去查找 package.path 的路径。 如果查找失败,接着使用 C 加载器去查找 package.cpath 的路径。 如果都失败了,再尝试 一体化 加载器 (参见 package.loaders。
每次找到一个加载器,require 都用一个参数调用加载器: modname 。 如果加载器返回非空值, require 将这个值赋给package.loaded[modname]。 如果加载器没能返回一个非空值用于赋给 package.loaded[modname], require 会在那里设入 true 。 无论是什么情况,require 都会返回 package.loaded[modname] 的最终值。
如果在加载或运行模块时有错误, 或是无法为模块找到加载器, require 都会抛出错误。
ulua 路径小记 以及 lua require 机制整理的更多相关文章
- 【转载】lua中的require机制
[转载自]http://blog.chinaunix.net/uid-552961-id-2736410.html lua中的require机制 为了方便代码管理,通常会把lua代码分成不同的模块,然 ...
- lua中的require机制
lua中的require机制 为了方便代码管理,通常会把lua代码分成不同的模块,然后在通过require函数把它们加载进来.现在看看lua的require的处理流程.1.require机制相关的数据 ...
- Lua require 相对路径
lua require 加载方式与我们现在熟知的路径系统不太一样,想要知道lua require 方法的工作原理也很简单 随便写一个错误的require 代码即可: 1 require("l ...
- lua require路径设置实例
1.首先要强调的是,lua require的路径用的是斜杠"/",而不是从Windows文件属性那里复制来的反斜杠"\". 2.通过 print(pagckag ...
- Lua Require函数
转自:http://www.cppblog.com/cslover/archive/2013/12/21/204934.html Lua提供高级的require函数来加载运行库.粗略的说require ...
- 扩展 lua require 的行为
扩展 lua require 的行为 来源 https://blog.codingnow.com/2015/10/lua_require_env.html 今天同事提了个需求,他希望可以给部分 lua ...
- cocos-Lua中的class与require机制
cocos-Lua中的class与require机制 local layer = require("PaiGow.src.GamePlayerListLayer")local Ga ...
- ectouch第七讲 之ECshop模板机制整理
网上的资源感觉还是有些用,可以看看,帮助理解,ECshop模板机制整理原文:http://blog.sina.com.cn/s/blog_6900af430100nkn8.html 一.模板引擎: E ...
- Lua 垃圾收集机制
1. 问题:一款用Lua做的游戏,玩了一段时间后会变卡 因为知道lua是有自动管理内存的机制,所以之前一直没有关注过lua内存的问题.所以今天好好的查看了lua垃圾收集机制.看了一下Lua的Garba ...
随机推荐
- Android中日期函数Calendar的一些用法和注意事项
1.月份获取时加1 Canlendar.MONTH + 1 因为使用的是罗马历,Calendar.MONTH返回的数值不是一年中月份的值,而是当前月份距离第一个月份的差值 如:当前月份为9月份,距离1 ...
- C#中IQueryable和IEnumberable的区别
IQueryable和IEnumberable的区别主要在查询方面有区别 IQueryable查询时间是先把skip和Take翻译成sql语句,去数据库执行完成后把数据加载到内存中 IEnumbera ...
- 用jQuery Mobile做HTML5移动应用的三个优缺点
JQuery Mobile 和 HTML5 的 3个优点 1. 上手迅速并支持快速迭代:在一个星期多一点的时间里,通过阅读JQuery Mobile文档以及O’Reilly出版的JQuery Mobi ...
- LCD底层驱动分析
根据分析的框架,自己写一个LCD驱动程序 1分析LCD硬件原理图 Von和Voff接的是一个电源电路,通过LCD_POWER接的是GPG4来控制LCD电源,高电平表示开启LCD电源 VM接的是CPU的 ...
- JavaScript Cookies
JavaScript Cookies 当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息.Cookies 的作用就是用于存储 web 页面的用户信息. Cookie ...
- Mysql 连接sleep状态问题解决。
昨日mysql总是出问题,各种程序在运行时,出现了连接已断开的问题. 导致此问题的原因: 1. 最大连接数 2. 网络问题 3. mysql服务器资源问题 然而,上面最常见的3个问题都没有出现.后来 ...
- export a java project to runable jar
When a java project needs to be transfered to another machine, e.g. vps, we need to export it to a r ...
- windows下Python shell代码自动补全
Unix下实现如题功能用下面的代码: import rlcompleter, readline readline.parse_and_bind('tab: complete') 但readline不能 ...
- 学习SVG系列(1):SVG基础
什么是SVG? 1.指可伸缩矢量图形 2.用来定义用于网络的基于矢量的图形 3.使用XML格式定义图形 4.图像在放大或改变尺寸的情况下其图形不会有所损失 5.万维网联盟的标准, 用于描述二维矢量图形 ...
- Gnu C的不同于标准C的语法
2. ,## 是与逗号合在一起用的, 表示后面有变量,则显示逗号,若后面无变量,则不显示逗号, 这种情况适用于用宏替换可变参数的函数,调用的时候可能传一个参数,或传两个参数, 这种打印语句在平台上,函 ...