Lua 详细教程
Lua 是一种轻量级、高效、可嵌入的脚本语言,广泛用于游戏开发、嵌入式系统和各种应用程序的扩展。以下是 Lua 的全面教程:
1. Lua 简介
主要特点
- 轻量级:核心解释器仅约 200KB
- 高效:执行速度快,内存占用低
- 可嵌入:易于集成到 C/C++ 程序中
- 动态类型:变量无需声明类型
- 自动内存管理:垃圾回收机制
- 多范式:支持过程式、面向对象和函数式编程
应用领域
- 游戏开发(如魔兽世界、愤怒的小鸟)
- 嵌入式系统
- 应用程序扩展
- 网络编程
- 科学计算
2. Lua 安装
Linux 安装
# Ubuntu/Debian
sudo apt-get install lua5.3
# CentOS/RHEL
sudo yum install lua
# 从源码安装
wget http://www.lua.org/ftp/lua-5.4.3.tar.gz
tar -zxvf lua-5.4.3.tar.gz
cd lua-5.4.3
make linux test
sudo make install
Mac 安装
brew install lua
Windows 安装
- 从官网下载二进制包:https://www.lua.org/download.html
- 解压并添加到 PATH 环境变量
验证安装
lua -v
3. Lua 基础语法
Hello World
lua
print("Hello, World!")
注释
lua
-- 单行注释
--[[
多行
注释
]]
变量
lua
-- 全局变量(默认)
a = 10
-- 局部变量
local b = 20
-- 变量命名规则
-- 字母、数字、下划线,不以数字开头
var_name = "value"
_var2 = 123
4. 数据类型
基本类型
lua
print(type("Hello")) --> string
print(type(10.4*3)) --> number
print(type(print))) --> function
print(type(type))) --> function
print(type(true))) --> boolean
print(type(nil))) --> nil
print(type(type(X)))) --> string
1. nil
lua
-- 表示无效值或空
local a
print(a) --> nil
2. boolean
lua
-- 只有 true 和 false 两个值
local isAlive = true
local isDead = false
3. number
lua
-- 所有数字都是双精度浮点数
local num = 123
local pi = 3.14159
local hex = 0x1A
local sci = 2e10
4. string
lua
-- 单引号或双引号
local str1 = "hello"
local str2 = 'world'
-- 多行字符串
local multi = [[
第一行
第二行
]]
-- 字符串连接
print("hello " .. "world") --> hello world
-- 字符串长度
print(#"hello") --> 5
5. table
lua
-- Lua 唯一的复合数据结构
local t = {} -- 空表
-- 数组形式
local arr = {10, 20, 30}
print(arr[1]) --> 10 (Lua 索引从1开始)
-- 字典形式
local dict = {name="Lua", version="5.4"}
print(dict["name"]) --> Lua
print(dict.name) --> Lua
-- 混合形式
local mix = {
"apple",
"banana",
price = 10.5,
[5] = "index 5"
}
6. function
lua
-- 函数是一等公民
local function add(a, b)
return a + b
end
-- 匿名函数
local sub = function(a, b)
return a - b
end
-- 函数作为参数
local function apply(func, a, b)
return func(a, b)
end
print(apply(add, 5, 3)) --> 8
7. userdata 和 thread
lua
-- userdata 用于表示 C 数据结构
-- thread 表示协程
5. 运算符
算术运算符
lua
print(10 + 20) --> 30
print(20 - 10) --> 10
print(10 * 20) --> 200
print(20 / 10) --> 2.0
print(20 % 3) --> 2
print(2 ^ 3) --> 8
关系运算符
lua
print(10 == 10) --> true
print(10 ~= 20) --> true
print(10 < 20) --> true
print(10 > 20) --> false
print(10 <= 20) --> true
print(10 >= 20) --> false
逻辑运算符
lua
print(true and false) --> false
print(true or false) --> true
print(not true) --> false
-- 短路求值
local a = 10
local b = 20
print(a > 0 and b > 0) --> true
其他运算符
lua
-- 字符串连接
print("hello" .. " " .. "world") --> hello world
-- 长度运算符
print(#{1, 2, 3}) --> 3
6. 控制结构
if 语句
lua
local age = 18
if age < 18 then
print("未成年")
elseif age >= 18 and age < 60 then
print("成年人")
else
print("老年人")
end
while 循环
lua
local i = 1
while i <= 5 do
print(i)
i = i + 1
end
repeat-until 循环
lua
local i = 1
repeat
print(i)
i = i + 1
until i > 5
for 循环
lua
-- 数值 for
for i = 1, 5 do
print(i)
end
-- 带步长
for i = 10, 1, -1 do
print(i)
end
-- 泛型 for (遍历表)
local t = {a=1, b=2, c=3}
for k, v in pairs(t) do
print(k, v)
end
-- 遍历数组
local arr = {"a", "b", "c"}
for i, v in ipairs(arr) do
print(i, v)
end
7. 函数
定义函数
lua
-- 基本形式
function greet(name)
return "Hello, " .. name
end
-- 局部函数
local function add(a, b)
return a + b
end
-- 匿名函数
local mul = function(a, b)
return a * b
end
多返回值
lua
function swap(a, b)
return b, a
end
x, y = swap(10, 20)
print(x, y) --> 20 10
可变参数
lua
function sum(...)
local s = 0
for _, v in ipairs({...}) do
s = s + v
end
return s
end
print(sum(1, 2, 3, 4)) --> 10
尾调用优化
lua
function foo(n)
if n > 0 then
return foo(n - 1)
end
return 0
end
8. 表(Table)
表的基本操作
lua
-- 创建表
local t = {}
-- 添加元素
t[1] = "first"
t["key"] = "value"
t.x = 10
-- 访问元素
print(t[1]) --> first
print(t["key"]) --> value
print(t.key) --> value
print(t.x) --> 10
-- 删除元素
t[1] = nil
表的方法
lua
local fruits = {"apple", "banana", "orange"}
-- 插入元素
table.insert(fruits, "pear") -- 末尾插入
table.insert(fruits, 2, "grape") -- 指定位置插入
-- 移除元素
table.remove(fruits) -- 移除最后一个
table.remove(fruits, 2) -- 移除指定位置元素
-- 排序
table.sort(fruits)
-- 连接
print(table.concat(fruits, ", ")) --> apple, banana, grape, orange
元表(Metatable)
lua
local t1 = {10, 20, 30}
local t2 = {40, 50, 60}
-- 设置元表
local mt = {
__add = function(a, b)
local result = {}
for i = 1, #a do
table.insert(result, a[i] + b[i])
end
return result
end
}
setmetatable(t1, mt)
setmetatable(t2, mt)
local t3 = t1 + t2
print(table.concat(t3, ", ")) --> 50, 70, 90
常用元方法
lua
__index -- 访问不存在的键时调用
__newindex -- 给不存在的键赋值时调用
__add -- +
__sub -- -
__mul -- *
__div -- /
__mod -- %
__pow -- ^
__concat -- ..
__eq -- ==
__lt -- <
__le -- <=
__call -- 把表当函数调用时
__tostring -- 转换为字符串时
9. 模块与包
创建模块
lua
-- mymodule.lua
local M = {} -- 模块表
function M.add(a, b)
return a + b
end
function M.sub(a, b)
return a - b
end
return M
使用模块
lua
local mymodule = require("mymodule")
print(mymodule.add(10, 5)) --> 15
print(mymodule.sub(10, 5)) --> 5
包管理(LuaRocks)
# 安装 LuaRocks
sudo apt-get install luarocks
# 安装包
luarocks install luasocket
# 搜索包
luarocks search json
10. 协程(Coroutine)
基本使用
lua
-- 创建协程
local co = coroutine.create(function()
print("协程开始")
coroutine.yield()
print("协程恢复")
end)
-- 运行协程
coroutine.resume(co) --> 协程开始
-- 恢复协程
coroutine.resume(co) --> 协程恢复
协程状态
lua
print(coroutine.status(co)) --> suspended/running/dead
数据交换
lua
local co = coroutine.create(function(a, b)
coroutine.yield(a + b, a - b)
return a * b
end)
print(coroutine.resume(co, 10, 5)) --> true 15 5
print(coroutine.resume(co)) --> true 50
11. 文件 I/O
简单模式
lua
-- 读取文件
local file = io.open("test.txt", "r")
local content = file:read("*a")
file:close()
-- 写入文件
local file = io.open("output.txt", "w")
file:write("Hello, Lua!")
file:close()
完全模式
lua
local file = assert(io.open("test.txt", "r"))
-- 逐行读取
for line in file:lines() do
print(line)
end
file:close()
12. 错误处理
pcall
lua
local status, err = pcall(function()
error("出错了!")
end)
if not status then
print("错误:", err) --> 错误: test.lua:2: 出错了!
end
xpcall
lua
local function errorHandler(err)
print("错误处理:", err)
end
local status = xpcall(
function()
error("出错了!")
end,
errorHandler
)
13. 标准库
字符串库
lua
local s = "Hello, Lua!"
-- 大小写转换
print(string.upper(s)) --> HELLO, LUA!
print(string.lower(s)) --> hello, lua!
-- 查找
print(string.find(s, "Lua")) --> 8 10
-- 截取
print(string.sub(s, 1, 5)) --> Hello
-- 格式化
print(string.format("PI = %.2f", math.pi)) --> PI = 3.14
-- 匹配模式
for word in string.gmatch(s, "%a+") do
print(word) --> Hello Lua
end
数学库
lua
print(math.sin(math.pi/2)) --> 1.0
print(math.floor(3.7)) --> 3
print(math.ceil(3.2)) --> 4
print(math.random(1, 100)) --> 随机数
print(math.max(10, 20)) --> 20
表库
lua
local t = {"a", "b", "c"}
-- 插入
table.insert(t, "d")
-- 移除
table.remove(t)
-- 排序
table.sort(t)
-- 连接
print(table.concat(t, ", ")) --> a, b, c
操作系统库
lua
print(os.time()) --> 当前时间戳
print(os.date("%Y-%m-%d")) --> 2023-01-01
os.execute("ls") --> 执行系统命令
14. 与 C 交互
从 Lua 调用 C 函数
// mylib.c
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static int l_add(lua_State *L) {
int a = luaL_checkinteger(L, 1);
int b = luaL_checkinteger(L, 2);
lua_pushinteger(L, a + b);
return 1;
}
static const struct luaL_Reg mylib[] = {
{"add", l_add},
{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 中使用:
lua
local mylib = require("mylib")
print(mylib.add(10, 20)) --> 30
从 C 调用 Lua
// main.c
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if (luaL_dofile(L, "script.lua")) {
printf("Error: %s\n", lua_tostring(L, -1));
}
lua_close(L);
return 0;
}
15. 最佳实践
代码风格
lua
-- 使用小写和下划线命名
local player_name = "John"
-- 常量使用大写
local MAX_SPEED = 100
-- 函数命名使用动词
function get_player_score(player_id)
-- ...
end
-- 缩进使用2个空格
if condition then
do_something()
end
性能优化
- 尽量使用局部变量
- 避免频繁创建和销毁表
- 使用 table.concat 连接大量字符串
- 预分配数组大小
- 避免不必要的垃圾回收
调试技巧
lua
-- 打印调试信息
print("Debug:", variable)
-- 使用 assert 检查条件
assert(type(var) == "number", "var should be a number")
-- 使用 debug 库
local info = debug.getinfo(1)
print("Current function:", info.name)
16. 实战示例
1. 简单计算器
lua
function calculate()
print("请输入第一个数字:")
local a = tonumber(io.read())
print("请输入运算符(+, -, *, /):")
local op = io.read()
print("请输入第二个数字:")
local b = tonumber(io.read())
local result
if op == "+" then
result = a + b
elseif op == "-" then
result = a - b
elseif op == "*" then
result = a * b
elseif op == "/" then
result = a / b
else
print("无效运算符")
return
end
print(string.format("结果: %.2f", result))
end
calculate()
2. 猜数字游戏
lua
math.randomseed(os.time())
local secret = math.random(1, 100)
local guess, attempts = 0, 0
print("猜数字游戏(1-100)")
while guess ~= secret do
print("请输入你的猜测:")
guess = tonumber(io.read())
attempts = attempts + 1
if guess < secret then
print("太小了!")
elseif guess > secret then
print("太大了!")
else
print(string.format("恭喜! 你用了 %d 次猜对了!", attempts))
end
end
3. 简单面向对象
lua
-- 定义类
local Person = {}
function Person:new(name, age)
local obj = {
name = name,
age = age
}
setmetatable(obj, self)
self.__index = self
return obj
end
function Person:introduce()
print(string.format("我叫 %s,今年 %d 岁", self.name, self.age))
end
-- 创建对象
local p = Person:new("张三", 25)
p:introduce()
Lua 是一门简洁而强大的语言,本教程涵盖了 Lua 的主要特性和用法。要精通 Lua 需要不断实践,建议通过实际项目来加深理解。