Lua中的require

來源:互聯網
上載者:User

標籤:blog   http   使用   strong   檔案   資料   

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.