首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Lua 模塊與包機制深度解析:require、module 與最佳實踐

     編輯:關於C語言

核心概念

  • 模塊:一個返回 table 的 Lua 文件,包含導出的函數、常量
  • 包:多個模塊的集合,通過目錄組織
  • require:加載模塊的標準函數
  • module:舊版創建模塊的函數(Lua 5.2+ 已棄用,不推薦使用)

require 工作流程詳解

1. 搜索路徑

require 使用 package.path(Lua 文件)和 package.cpath(C 庫)作為搜索路徑,路徑項以 ; 分隔,? 為模塊名佔位符。

-- package.path 示例
;.\?.lua;D:\Lua\5.1\lua\?.lua;D:\Lua\5.1\lua\?\init.lua;...

-- require "mod" 依次嘗試
mod
mod.lua
c:\windows\mod
/usr/local/lua/mod/mod.lua

2. 加載機制

  1. 檢查 package.loaded[modname],若存在直接返回
  2. 按路徑查找文件
  3. Lua 文件 → loadfile 加載;C 庫 → loadlib 加載
  4. 以模塊名為參數調用加載塊(執行模塊代碼)
  5. 將返回值存入 package.loaded[modname] 並返回

3. 找不到模塊時的錯誤輸出

require "jellythink"
-- 錯誤信息會列出所有嘗試過的路徑

模塊命名技巧:連字符重命名

C 庫模塊無法修改內部 luaopen_* 函數名,但 require 支援連字符重命名:

  • require "a-b" 會查找 luaopen_b 而非 luaopen_a-b
  • 利用此特性可加載同一 C 庫的不同版本(如 mylib-v1, mylib-v2)

編寫現代 Lua 模塊(推薦模式)

基本模板

local M = {}  -- 內部實現表

function M.new(r, i) return {r = r, i = i} end

M.i = M.new(0, 1)  -- 常量

function M.add(c1, c2)
    return M.new(c1.r + c2.r, c1.i + c2.i)
end

function M.sub(c1, c2)
    return M.new(c1.r - c2.r, c1.i - c2.i)
end

return M  -- 導出

保存為 complex.lua,使用時:

local complex = require "complex"
local c1 = complex.new(1, 2)
local c2 = complex.new(3, 4)
print(complex.add(c1, c2).r)  -- 4

無污染模式(利用 require 傳入模塊名)

local moduleName = ...
local M = {}
_G[moduleName] = M
package.loaded[moduleName] = M  -- 省略 return

function M.new(r, i) return {r=r, i=i} end
-- ... 其他函數直接用 M.xxx

-- 無需 return M

優點:文件重命名即模塊重命名,內部無硬編碼模塊名。

環境機制進階:_ENV (Lua 5.2+)

為模塊設置專屬 _ENV,所有全局變量自動收集到模塊 table:

local _ENV = {}
function new(r, i) return {r=r, i=i} end
i = new(0, 1)
function add(c1, c2) return new(c1.r+c2.r, c1.i+c2.i) end
return _ENV

此模式下無需前綴 M.,代碼極度簡潔。

package.loaded 緩存機制

  • 首次 require → 加載並緩存返回值
  • 再次 require → 直接返回緩存值,不重複執行模塊代碼
  • 熱更新需手動 package.loaded[mod] = nil 後再 require

總結

現代 Lua 模塊開發核心原則:局部表實現、返回導出、利用 package.loaded 緩存、善用 _ENV 簡化代碼。摒棄舊版 module(),擁抱模塊化、可重命名、可熱更新的模塊設計。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved