Lua中的require(转)

lua中的require机制
    为了方便代码管理,一般会把lua代码分红不一样的模块,而后在经过require函数把它们加载进来。如今看看lua的require的处理流程。
一、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扩展的细节了^_^。html

转自:http://blog.chinaunix.net/uid-552961-id-2736410.htmlpython

http://www.cnblogs.com/sifenkesi/p/3816788.html函数

相关文章
相关标签/搜索