lua中的require机制
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扩展的细节了^_^。
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函数把它们加载进来.现在看看lua的require的处理流程.1.require机制相关 ...
- lua中的坑
在工作中使用lua也有一年了,代码也写了不少,踩过不少坑,这里记录一下. table.sort table.sort是lua自带的排序函数,数据量小时,也还是不错的.不过要注意你传入的compare函 ...
- ulua 路径小记 以及 lua require 机制整理
ulua 路径小记 在学习ulua时,require模块的根路径可以为项目的Lua文件夹或者ToLua文件夹(Editor下),但是在package.path和package.cpath中并没有看到当 ...
- cocos-Lua中的class与require机制
cocos-Lua中的class与require机制 local layer = require("PaiGow.src.GamePlayerListLayer")local Ga ...
- Lua中的loadfile,dofile,require使用,最后还有调试
1.loadfile---只编译,不运行. loadfile编译代码成中间码并且返回编译后的chunk作为一个函数,而不执行代码:另外loadfile不会抛出错误信息而是返回错误代号. loadstr ...
- lua中基类和“继承机制”
基类:基类定义了所有对于派生类来说普通的属性和方法,派生类从基类继承所需的属性和方法,且在派生类中增加新的属性和方法. 继承:继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类. lu ...
- lua 面向对象编程类机制实现
lua no class It is a prototype based language. 在此语言中没有class关键字来创建类. 现代ES6, 已经添加class类. prototype bas ...
随机推荐
- Openlayers系列(一)关于地图投影的理解
背景 近期开发以MongoDB为基础的分布式地理数据管理平台系统,被要求做一个简单的demo给客户进行演示.于是笔者便打算向数据库中存储一部分瓦片数据,写一个简单的存取服务器,使用Openlayers ...
- 尝试在Linux上部署Asp.net Core应用程序
快两个月没接触.net,倒是天天在用Linux,所以想尝试一下在Linux运行喜欢的.net 应用. 安装CentOS 安装.Net core for Linux 创建Asp.net Core应用程序 ...
- JSON和java对象的互转
先说下我自己的理解,一般而言,JSON字符串要转为java对象需要自己写一个跟JSON一模一样的实体类bean,然后用bean.class作为参数传给对应的方法,实现转化成功. 上述这种方法太麻烦了. ...
- notepad的快捷操作-代码速写
(一)先安装zencode插件 (二)运用插件 第一步:键入:html:xt 再Ctrl+Alt+Enter键 得到 <!DOCTYPE html PUBLIC "-//W3C//DT ...
- 程序编译没错,运行报错:无法定位程序输入点GT_BufLaserFollowRatio(这是函数)于动态链接库GTS.DLL上
:DLL里面没有导出该函数 :DLL没放进DEBUGS文件夹 (当时的情况是这个)
- JS获取随机的16位十六进制的数
直接上代码: function getRamNumber(){ var result=''; for(var i=0;i<16;i++){ result+=Math.floor(Math.ran ...
- php使用PHPMailer邮件类发送邮件
PHPMailer是一个用于发送电子邮件的PHP函数包.它提供的功能包括:*.在发送邮时指定多个收件人,抄送地址,暗送地址和回复地址*.支持多种邮件编码包括:8bit,base64,binary和qu ...
- C语言程序设计第一作业
C语言程序设计第一作业 实验总结 (一) 1.题目:输入圆的半径,求圆周长和面积 2.流程图: 3.测试数据及运行结果: 4.实验分析: 问题1: 出现了错误 原因:是在赋值那写反了 解决方法:应该是 ...
- python random从集合中随机选择元素
1.使用python random模块的choice方法随机选择某个元素 from random import choice foo = ['a', 'b', 'c', 'd', 'e'] print ...
- zoj1151 zoj1295 Word Reversal 字符串的简单处理
Word Reversal Time Limit: 2 Seconds Memory Limit:65536 KB For each list of words, output a line ...