今天我们继续学习lua里的模块还有包
首先说一下这两个东西的概念
模块(module)
Lua 的模块是由变量、函数等已知元素组成的 table,然后把需要导出的常量、函数放入其中
特殊之处就是模块返回值 就是这个表
1 2 3 4 5 6 7 8 9 10 11 12
| local utils = {}
function utils.add(a, b) return a + b end
function utils.sub(a, b) return a - b end
return utils
|
但是怎么用呢,其实,Lua 模块 ≈ C# 的 命名空间 + 静态类 + 单例实例
相同含义的C#语句就是
1 2 3 4 5 6 7 8
| namespace Utils { public static class Math { public static int Add(int a, int b) => a + b; public static int Sub(int a, int b) => a - b; } }
|
使用就是不需要实现类的实例,直接using引入命名空间然后点语法使用里面的属性就行
1 2 3 4 5 6 7 8 9 10
| using Utils;
class Program { static void Main() { int result = Math.Add(1, 2); Console.WriteLine(result); } }
|
这里在lua中的使用方法就是使用require函数
require 函数
要使用文件使用一个模块使用require函数
或者
执行 require 后会返回一个由模块常量或函数组成的 table,并且还会定义一个包含该 table 的全局变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
module = {}
module.constant = "这是一个常量"
function module.func1() io.write("这是一个公有函数!\n") end
local function func2() print("这是一个私有函数!") end
function module.func3() func2() end
return module
|
然后我们在另外一个文件启用
1 2 3 4 5 6 7
|
require("module")
print(module.constant)
module.func3()
|


但是大家可能会遇到的误区就是误以为模块里定义的表名就是文件名,其实不是的,
此时我们就可以把这个module.lua当做命名空间,然后modele.lua里面的属性和函数视作C#里的静态static函数,使用直接用点语法就行

require函数的原理
当你写:
Lua 会做一件事: 到一堆“固定路径”里去找 module.lua,也就是它会尝试从 Lua 文件或 C 程序库中加载模块
require 用于搜索 Lua 文件的路径是存放在全局变量 package.path 中,当 Lua 启动后,会以环境变量 LUA_PATH(这里我用的是我自定义的LUA_HOME,因为我的是lua5.4) 的值来初始这个环境变量。如果没有找到该环境变量,则使用一个编译时定义的默认路径来初始化。
其实就是我们设置的path路径

lua会去这个路径package.path去找路径

而在这些路径里
1
| D:\ZeroBraneStudio\lua-5.4.2_Win64_bin\lua\?.lua;D:\ZeroBraneStudio\lua-5.4.2_Win64_bin\lua\?\init.lua;D:\ZeroBraneStudio\lua-5.4.2_Win64_bin\?.lua;D:\ZeroBraneStudio\lua-5.4.2_Win64_bin\?\init.lua;D:\ZeroBraneStudio\lua-5.4.2_Win64_bin\..\share\lua\5.4\?.lua;D:\ZeroBraneStudio\lua-5.4.2_Win64_bin\..\share\lua\5.4\?\init.lua;.\?.lua;.\?\init.lua;D:\ZeroBraneStudio\lua-5.1.5-52\5.1\lua\?.luac
|
可以看到有很多问号“?”,而问号就是占位符
使用require(“module”)函数会把问号替换为module,然后lua会开始查找这个moule.lua文件,然后转换为类似执行过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| if package.loaded["module"] then return package.loaded["module"] end
local path = "./module.lua"
local f = loadfile(path)
local result = f()
package.loaded["module"] = result
return result
|
而返回值就是刚才的模块里的表
包(package)
Lua里有一个全局变量:package
它其实是一个大工具箱,里面专门负责:
主要的四个功能就是
① package.path (控制 Lua 模块搜索路径)
控制:Lua 去哪里找 .lua 文件
② package.loaded (缓存机制)
控制:模块是否重复加载
③ package.cpath(C模块)
用来找 .dll / .so
④ package.preload(虚拟模块)
手动注册模块(不需要文件)
评论区