模組類似於乙個封裝庫,從lua 5.1開始,lua加入了標準的模組管理機制,可以把一些公用的**放在乙個檔案裡,以api介面的形式在其他地方呼叫,有利於**的重用和降低**耦合度。
lua的模組是由變數、函式等已知元素組成的table,因此建立乙個模組很簡單,就是建立乙個table,然後把需要匯出的常量、函式放入其中,最後返回這個table就行了。以下為建立自定義模組 module。lua,檔案**格式如下:
-- 檔名為 module.lua
-- 定義乙個名為 module 的模組
module =
-- 定義乙個常量
module.constant =
"這是乙個常量"
-- 定義乙個函式
function module.
func1()
io.write
("這是乙個公有函式!\n"
)end
local function func2()
print
("這是乙個私有函式!"
)end
function module.
func3()
func2()
end
return module
由上可知,模組的結構就是乙個 table 的結構,因此可以像操作呼叫 table 裡的元素那樣來操作呼叫模組裡的常量或函式。
上面的 func2 宣告為程式塊的區域性變數,即表示乙個私有函式,因此是不能從外部訪問模組裡的這個私有函式,必須通過模組裡的公有函式來呼叫.
lua提供了乙個名為require的函式用來載入模組。要載入乙個模組,只需要簡單地呼叫就可以了。例如:
require
("《模組名》"
)
或者
require "《模組名》"
執行require後會返回乙個由模組常量或函式組成地table,並且還會定義乙個包含該table地全域性變數。
test_module.lua 檔案
-- test_module.lua 檔案
-- module 模組為上文提到到 module.lua
require
("module"
)print
(module.constant)
module.
func3
()
以上**執行結果為:
這是乙個常量
這是乙個私有函式!
或者給載入的模組定義乙個別名變數,方便呼叫:
test_module2.lua 檔案
-- test_module2.lua 檔案
-- module 模組為上文提到到 module.lua
-- 別名變數 m
local m =
require
("module"
)print
(m.constant) m.
func3
()
以上**執行結果為:
這是乙個常量
這是乙個私有函式!
對於自定義的模組,模組檔案不是放在那個檔案目錄都行,函式require有它自己的檔案路徑載入策略,它會嘗試從lua檔案或c程式庫中載入模組。
require 用於搜尋lua檔案的路徑是存放在全域性變數package.path中,當lua啟動後,會以環境變數lua_path的值來初始化這個環境變數。如果沒有找到該環境變數,則使用乙個編譯時定義的預設路徑來初始化。
當然,如果沒有lua_path這個環境變數,也可以自定義設定,在當前使用者根目錄下開啟.profile檔案(沒有則建立,開啟.bashrc檔案也可以),例如把"~/lua/"路徑加入lua_path環境變數裡:
#lua_path
export lua_path=
"~/lua/?.lua;;"
檔案路徑以";「號分隔,最後的2個」;;"表示新加的路徑後面加上原來的預設路徑。
接著,更新環境變數引數,使之立即生效。
source ~
/.profile
這時假設 package.path 的值是:
/users/dengjoe/lua/
?.lua;./
?.lua;
/usr/local/share/lua/
5.1/
?.lua;
/usr/local/share/lua/
5.1/
?/init.lua;
/usr/local/lib/lua/
5.1/
?.lua;
/usr/local/lib/lua/
5.1/
?/init.lua
那麼呼叫 require(「module」) 時就會嘗試開啟以下檔案目錄去搜尋目標。
/users/dengjoe/lua/module.lua;
./module.lua
/usr/local/share/lua/
5.1/module.lua
/usr/local/share/lua/
5.1/module/init.lua
/usr/local/lib/lua/
5.1/module.lua
/usr/local/lib/lua/
5.1/module/init.lua
如果找過目標檔案,則會呼叫package.loadfile 來載入模組。否則,就會去找c程式庫。
搜尋的檔案路徑是從區域性變數package.cpath獲取,而這個變數則是通過環境變數 lua_cpath來初始。
搜尋的策略跟上面一樣,只不過現在換成搜尋的是so或dll型別檔案。如果找得到,那麼require就會通過package.loadlib來載入它。
lua和c是很容易結合的,使用c為lua寫包。
與lua中寫包不同,c包在使用之前必須首先載入並連線,在大多數系統中最容易的實現方式是通過動態鏈結庫機制。
lua在乙個叫loadlib的函式內提供了所有的動態連線的功能。這個函式有兩個引數:庫的絕對路徑和初始化函式。所以典型的呼叫的例子如下:
local path =
"/usr/local/lua/lib/libluasocket.so"
local f =
loadlib
(path,
"luaopen_socket"
)
loadlib函式載入指定的庫並且連線到lua,然而它並不開啟庫(也就是說沒有呼叫初始化函式),反之他返回初始化函式作為lua的乙個函式,這樣我們可以直接在lua中呼叫他。
如果載入動態庫或者查詢初始化函式時出錯,loadlib將返回nil和錯誤資訊。我們可以修改前面一段**,使其檢測錯誤然後呼叫初始化函式:
local path =
"/usr/local/lua/lib/libluasocket.so"
-- 或者 path =
"c:\\windows\\luasocket.dll",這是 window 平台下
local f =
assert
(loadlib
(path,
"luaopen_socket"))
f()-- 真正開啟庫
一般情況下我們期望二進位制的發布庫包含乙個與前面**段相似的stub檔案,安裝二進位制庫的時候可以隨便放在某乙個目錄,只需要修改stub檔案對應二進位制庫的實際路徑即可。
將stub檔案所在的目錄加入到lua_path,這樣設定後就可以使用require函式載入c庫了。
function require
(name)
if not package.loaded[name] then
local loader =
findloader
(name)
if loader == nil then
error
("unable to load module"
.. name)
endpackage.loaded[name]
=true
local res =
loader
(name)
if res ~
= nil then
package.loaded[name]
= res
endend
return package.loaded[name]
end
Lua 模組與包
模組類似於乙個封裝庫,從 lua 5.1 開始,lua 加入了標準的模組管理機制,可以把一些公用的 放在乙個檔案裡,以 api 介面的形式在其他地方呼叫,有利於 的重用和降低 耦合度。lua 的模組是由變數 函式等已知元素組成的 table,因此建立乙個模組很簡單,就是建立乙個 table,然後把需...
Lua 模組與包
從使用者觀點來看,乙個模組就是乙個程式庫,可以通過require來載入 require用於使用模組,module用於建立模組 然後便得到了乙個全域性變數,表示乙個table,這個table就像乙個名字空間,其內容就是模組中匯出的所有東西,例如函式和變數。乙個規範的模組還應使require返回這個ta...
lua 模組與包 五
模組類似於1個封裝庫,從lua 5.1 開始,lua加入了標準的模組管理機制,可以把一些公用的 放在乙個檔案裡,以api介面的形式在其他地方呼叫,用利於 的重用和降低 的耦合度。lua的模組是由變數 函式等已知元素組成的table,因此建立1個模組就是建立1個table,把 需要匯出的常量 函式放入...