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函數