Chapter 15_1 require函數

來源:互聯網
上載者:User

標籤:

  Lua提供了一個名為require的高層函數來載入模組,但這個函數只假設了關於模組的基本概念。

對於require而言,一個模組就是一段定義了一些值(函數或者包含函數的table)的代碼。

為了載入一個模組,只需要簡單調用require "modname" 。這個函數首先會尋找package.loaded表,檢查modname是否載入過。

如果載入過,require返回package.loaded[modname]中的值。

否則,它試著為模組尋找“載入器”。

首先require會搜尋Lua file 。如果找到lua檔案,就調用loadfile載入,它的傳回值是函數 即"載入器"。

如果找不到Lua檔案,會尋找C庫,如果找到,就調用package.loadlib載入,去尋找luaopen_modname標誌函數。

每次找到載入器,require就用兩個參數調用載入器:modname和一個在擷取載入器過程中得到的參數(如果通過尋找檔案得到的載入器,這個額外參數就是檔案名稱)。

如果載入器返回非空值,require將這個值賦給package.loaded[modname].否則也會為其設定true值,無論什麼情況,require都會返回package.loaded[modname]的最終值。如果在載入或運行時有錯誤,或是無法為模組找到載入器,require都會拋出錯誤。

如果要用require載入模組兩次,我們可以把package.loaded[modname]給擦除掉。

packag.loaded.[modname] = nil

有時需要講一個模組改名,以避免名字衝突。比如同一個模組有不同版本的情況。對於一個lua檔案來說,改掉名字就可以了。

但是對於一個C程式庫,我們就不能編輯其中的luaopen_*函數的名稱了。為此,require用到了一個小技巧:

如果一個模組中包含了連字號 " - " ,require就會用連字號後的內容來建立luaopen_*函數名。

比如一個模組名為module-hello,require就會認為它的open函數是luaopen_hello,並不是luaopen_a-b。

因為在C文法中,連字號作為函數名是非法的。

因此,如果我們需要用兩個同名的mod模組,可以把其中一個重新命名為mod-hello,一個命名為mod-world。

當調用

m1 = require "mod-hello"

require函數會找到這個mod-hello檔案,並且在這個檔案裡,去找luaopen_mod函數。

注意:Lua5.2與Lua5.3這裡是完全相反:5.2移除"-"之前的,5.3移除“-”之後的。

Lua5.3的版本,如果遇到a.b.c-v2.1的模組名,函數名就是luaopen_a_b_c。橫線後的都忽略掉。

路徑搜尋

  當搜尋一個Lua檔案的時候,rquire用的的路徑是一系列樣板(templates),其中的每一個指定了模組的檔案名稱。

在每個路徑樣板中都包含了一個可選的‘?‘符號,require會用模組名去替代這個問號(如果有的話),再去檢查這個檔案是否存在。

如果該樣板沒有,就從下一個樣板繼續尋找。這些路徑樣板被";"一個個隔開:

?;?.lua;c:\Windows\?;/usr/local/lua/?/?.lua

require "mod" 語句會尋找下面的檔案:

modmod.luac:\Windows\mod/usr/loacl/lua/mod/mod.lua

require只處理 ";" 和 "?" 符號,其他符合則是路徑自己定義的。

require找lua檔案時路徑變數是package.path。Lua一開始會用LUA_PATH_5_3環境變數去初始化它。

如果沒有定義這個環境變數,就會用LUA_PATH。如果兩個都沒有定義,Lua會用luaconf.h裡的預設路徑。

環境變數中出現的所有“;;”都會被替換成預設路徑。

比如你把LUA_PATH_5_3設定為“mydir/?.lua;;”,最後的路徑會是"mydir/?.lua"之後跟著的是預設路徑。

require尋找C庫的方法也是一樣的,但是變數變成了package.cpath。初始化的時候使用的是LUA_CPATH_5_3和LUA_CPATH。

在UNIX中是這樣的:

./?.so;/usr/local/lib/lua/5.3/?.so

package.searchpath函數包含了所有搜尋庫的規則,它接收一個模組名和一個路徑。

路徑是一系列以分號分隔的模板構成的字串,在其中搜尋指定的name。

返回第一個可以用讀模式開啟(並馬上關閉該檔案)的檔案的名字。如果不存在這樣的檔案,即返回nil加上錯誤訊息。

該錯誤訊息列出所有嘗試開啟的檔案名稱。

搜尋器

  用於require控制如何載入模組的表--package.searchers

表內的每一項都是一個尋找器函數,當尋找一個模組時,require按照次序調用這些尋找器,並傳入唯一的模組名參數。

成功則返回另一個函數(模組的載入器)和一個載入器需要的參數。nil則表示錯誤。

Lua用四個尋找器函數初始化該表:

1>  在package.preload表中尋找載入器,沒有傳回值。

2>  尋找Lua庫的載入庫,用儲存在package.path中的路徑來尋找

3>  尋找C庫的載入庫,使用儲存在package.cpath中的路徑。

4>  一體化載入器,從C路徑中尋找指定模組的根名字。例如“a.b.c”;它將尋找a這個庫。如果找到就會在裡面找子模組的載入函數,就是找luaopen_a_b_c。

比如尋找 “hello.core” 模組,就是尋找hello庫的core子模組。對應的函數就是luaopen_hello_core。

這樣可以把若干C子模組打包進單個庫。每個子模組都可以有原本的載入函數名。

 以上內容來自:《Lua程式設計第二版》和《Programming in Lua  third edition 》

Chapter 15_1 require函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.