On this page

Lua 模块与包

Lua 模块与包管理详解

Lua 的模块系统允许将代码组织成可重用的单元,以下是 Lua 模块与包管理的完整指南:

1. 创建模块

传统模块模式

-- mymodule.lua
local M = {} -- 模块表

-- 私有局部变量
local privateVar = "secret"

-- 公有函数
function M.hello()
    print("Hello from module!")
end

-- 私有函数
local function privateFunc()
    print("This is private")
end

function M.publicFunc()
    privateFunc() -- 可以访问私有函数
    return privateVar
end

return M -- 返回模块表

使用环境隔离

-- modenv.lua
local _M = {} -- 模块表
local mt = { __index = _M }

setmetatable(_M, {
    __newindex = function(_, k, v)
        error("Attempt to write to undeclared var " .. k, 2)
    end
})

function _M.new()
    return setmetatable({}, mt)
end

return _M

2. 使用模块

基本使用

local mymodule = require("mymodule")
mymodule.hello()

重命名模块

local mm = require("mymodule")
mm.hello()

3. 包管理系统

LuaRocks (官方包管理器)

安装:

# Linux/macOS
wget https://luarocks.org/releases/luarocks-x.y.z.tar.gz
tar zxpf luarocks-x.y.z.tar.gz
cd luarocks-x.y.z
./configure && make && sudo make install

# Windows
# 下载预编译包并安装

常用命令:

luarocks install module-name  # 安装模块
luarocks search pattern      # 搜索模块
luarocks list                # 已安装模块列表
luarocks remove module-name  # 移除模块

创建自己的包

  1. 创建 rockspec 文件:

    -- mypackage-1.0-1.rockspec
    package = "mypackage"
    version = "1.0-1"
    source = {
     url = "git://github.com/me/mypackage.git"
    }
    description = {
     summary = "My awesome package",
     homepage = "https://github.com/me/mypackage",
     license = "MIT"
    }
    dependencies = {
     "lua >= 5.1"
    }
    build = {
     type = "builtin",
     modules = {
         mypackage = "mypackage.lua"
     }
    }
    
  2. 打包并发布:

    luarocks pack mypackage-1.0-1.rockspec
    luarocks upload mypackage-1.0-1.src.rock
    

4. 模块搜索路径

Lua 使用 package.pathpackage.cpath 查找模块:

print(package.path)  -- 查看Lua模块搜索路径
print(package.cpath) -- 查看C模块搜索路径

自定义搜索路径:

-- 添加新路径
package.path = package.path .. ";./mylibs/?.lua"

-- 临时修改
local old_path = package.path
package.path = "./special/?.lua"
require("specialmod")
package.path = old_path

5. 高级模块技术

子模块系统

-- mypkg/init.lua
local M = {}

function M.new()
    return setmetatable({}, { __index = M })
end

return M

-- mypkg/submod.lua
local parent = (...):match("(.-)[^%.]+$")
local M = require(parent .. "init")

function M.subfunc()
    print("From submodule")
end

return M

热重载模块

function reload_module(name)
    package.loaded[name] = nil
    return require(name)
end

-- 使用
local mymod = reload_module("mymodule")

6. 最佳实践

  1. 模块设计原则

    • 单一职责原则
    • 最小化公开接口
    • 明确依赖关系
  2. 性能考虑

    -- 在模块中局部化常用函数
    local print = print
    local table_insert = table.insert
    
  3. 文档规范

    --- 计算两个数的和
    -- @param a number 第一个数
    -- @param b number 第二个数
    -- @return number 两数之和
    function M.add(a, b)
        return a + b
    end
    
  4. 错误处理

    function M.safe_divide(a, b)
        if b == 0 then
            return nil, "division by zero"
        end
        return a / b
    end
    

7. 与C模块交互

加载C模块

local my_cmod = require("mylib")  -- 加载mylib.so/mylib.dll

编写C模块示例

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

static int l_hello(lua_State *L) {
    printf("Hello from C!\n");
    return 0;
}

static const luaL_Reg mylib[] = {
    {"hello", l_hello},
    {NULL, NULL}
};

int luaopen_mylib(lua_State *L) {
    luaL_newlib(L, mylib);
    return 1;
}

编译为共享库:

gcc -shared -fPIC -o mylib.so mylib.c -I/usr/local/include -L/usr/local/lib -llua

Lua 的模块系统既简单又灵活,结合 LuaRocks 包管理器可以构建复杂的应用程序。合理组织模块结构对大型项目开发至关重要。