标准库
LuaJIT 提供一组默认可用的标准库,用于处理字符串、表、协程、数学计算、文件、时间、调试和模块加载
全局函数
这些函数不属于某个命名库,可以直接调用。
assert(v [, message])
断言 v 为真值,否则抛出错误。
local file = io.open("config.json", "r")
assert(file, "config.json not found")error(message [, level])
抛出一个 Lua 错误。
local function requireString(value)
if type(value) ~= "string" then
error("expected string", 2)
end
endgetmetatable(value)
获取对象元表。
local mt = getmetatable({})
print(mt)setmetatable(table, metatable)
设置表的元表。
local mt = {
__index = function()
return "default"
end
}
local t = setmetatable({}, mt)
print(t.name)ipairs(table)
按整数索引 1..n 顺序遍历数组部分。
for index, value in ipairs({ "a", "b", "c" }) do
print(index, value)
endpairs(table)
遍历表中的所有键值对。
for key, value in pairs({ name = "AsLua", runtime = "LuaJIT" }) do
print(key, value)
endnext(table [, index])
pairs 底层使用的原语,用于迭代表。
pcall(f, ...)
保护调用,失败时不直接中断脚本。
local ok, result = pcall(function()
return require("missing")
end)
print(ok, result)xpcall(f, err)
带错误处理函数的保护调用,常配合 debug.traceback 使用。
local ok, err = xpcall(function()
error("boom")
end, function(message)
return debug.traceback(message, 2)
end)
print(ok, err)print(...)
标准 Lua 中它会输出到宿主标准输出;在 AsLua 中,print 会被 LuaActivity 重写为日志输出函数,内容会显示在 AsLua 的日志界面中。
print("Hello AsLua")rawequal(a, b)
绕过 __eq 元方法,直接比较两个值。
rawget(table, key)
绕过 __index 直接读取字段。
rawset(table, key, value)
绕过 __newindex 直接写入字段。
rawlen(value)
返回对象原始长度,不触发元方法。
select(index, ...)
获取可变参数中的某一部分。
local function demo(...)
print(select("#", ...))
print(select(2, ...))
end
demo("a", "b", "c")tonumber(value [, base])
转换为数字。
print(tonumber("42"))
print(tonumber("ff", 16))tostring(value)
转换为字符串。对 Java 对象来说,AsLua 里更常见的是 luakt.tostring(obj),但普通 Lua 值仍然直接使用 tostring。
type(value)
返回值类型:
nilbooleannumberstringtablefunctionuserdatathread
unpack(list [, i [, j]])
将数组元素展开为多个返回值。
local args = { "a", "b", "c" }
print(unpack(args))loadstring(string [, chunkname])
从字符串加载 Lua 代码。
local fn = assert(loadstring("return 1 + 2"))
print(fn())loadfile(filename)
从文件加载 Lua 代码。
local fn = assert(loadfile("main.lua"))dofile(filename)
加载并立刻执行文件。
dofile("bootstrap.lua")collectgarbage([opt [, arg]])
控制 Lua GC。
collectgarbage("collect")coroutine 库
Lua 协程提供协作式并发,不是系统线程。
coroutine.create(f)
创建协程。
local co = coroutine.create(function()
print("step 1")
coroutine.yield("pause")
print("step 2")
end)coroutine.resume(co [, val1, ...])
恢复执行协程。
local ok, value = coroutine.resume(co)
print(ok, value)coroutine.yield(...)
挂起当前协程并返回控制权。
coroutine.status(co)
返回协程状态:
runningsuspendednormaldead
coroutine.wrap(f)
返回一个包装函数,调用时自动 resume。
coroutine.running()
返回当前运行中的协程。
table 库
table 是 Lua 最重要的数据结构库。
table.insert(list [, pos], value)
插入元素。
local t = { "a", "c" }
table.insert(t, 2, "b")table.remove(list [, pos])
移除元素并返回被删除的值。
table.concat(list [, sep [, i [, j]]])
拼接字符串数组。
print(table.concat({ "Lua", "JIT" }, "-"))table.sort(list [, comp])
原地排序。
local numbers = { 3, 1, 2 }
table.sort(numbers)table.foreach(table, f)
旧式遍历函数,通常不推荐新代码使用。
table.foreachi(table, f)
旧式数组遍历函数,通常不推荐新代码使用。
table.maxn(table)
返回数值索引中的最大索引。属于旧式 API,新代码一般直接维护自己的长度语义。
string 库
LuaJIT 的字符串是字节串,适合处理文本和二进制数据。
string.byte(s [, i [, j]])
返回字符串指定位置的字节值。
string.char(...)
按字节值构造字符串。
string.find(s, pattern [, init [, plain]])
查找子串或模式。
local i, j = string.find("hello world", "world")
print(i, j)string.format(format, ...)
格式化字符串。
print(string.format("id=%04d", 12))string.gmatch(s, pattern)
返回一个迭代器,遍历所有匹配项。
for word in string.gmatch("a,b,c", "[^,]+") do
print(word)
endstring.gsub(s, pattern, repl [, n])
替换字符串中的匹配内容。
print(string.gsub("hello world", "world", "LuaJIT"))string.len(s)
返回字节长度。
string.lower(s)
转小写。
string.upper(s)
转大写。
string.match(s, pattern [, init])
按模式提取内容。
local name = string.match("name=Hello", "name=(.+)")
print(name)string.rep(s, n)
重复字符串。
string.reverse(s)
反转字符串。
string.sub(s, i [, j])
截取子串。
print(string.sub("abcdef", 2, 4))string.dump(function)
导出函数的字节码表示。
WARNING
字节码与运行时实现相关,通常只在工具链、缓存或调试场景下使用。
buffer 库
它提供可变字符串缓冲区,适合高频拼接、分段读取、二进制写入和 Lua 值序列化。
通常这样加载:
local buffer = require("string.buffer")TIP
多数缓冲区方法会返回 buffer 自身,因此可以链式调用。
local b = buffer.new()
b:put("Hello", " ", "AsLua")
print(tostring(b))buffer.new([size] [, options])
创建新的 buffer。
local b1 = buffer.new()
local b2 = buffer.new(1024)第一个参数可以是预分配大小。如果提供 options table,可以传入:
dictmetatable
它们用于 encode / decode 的字典与元表序列化配置。
也可以只传 options:
local b = buffer.new({
dict = {}
})buffer.encode(value)
把 Lua 值序列化为字符串。
local payload = buffer.encode({
name = "AsLua",
runtime = "LuaJIT"
})buffer.decode(string)
把 buffer.encode 生成的字符串反序列化为 Lua 值。
local value = buffer.decode(payload)
print(value.name)b:put(...)
向 buffer 追加多个值。
支持:
- 字符串
- 整数
- 浮点数
- 另一个 buffer
- 带
__tostring元方法的对象
local b = buffer.new()
b:put("id=", 1001, ", name=", "AsLua")
print(tostring(b))WARNING
不能把 buffer 自己追加到自己,否则会报错。
b:putf(format, ...)
按格式化规则写入内容。
local b = buffer.new()
b:putf("id=%04d name=%s", 12, "AsLua")
print(tostring(b))b:get([n1 [, n2 ...]])
从当前读指针读取内容,并推进读指针。
无参数时等同于读取剩余全部内容:
local b = buffer.new()
b:put("abcdef")
print(b:get(2)) -- ab
print(b:get(2)) -- cd
print(b:get()) -- ef一次传多个长度会返回多个字符串:
local b = buffer.new()
b:put("abcdef")
local a, c = b:get(2, 4)
print(a, c)b:skip(n)
跳过 n 个字节。
local b = buffer.new()
b:put("abcdef")
b:skip(2)
print(b:get()) -- cdefb:reset()
重置 buffer 内容,并返回 buffer 自身。
b:free()
释放 buffer 内部存储,并返回 buffer 自身。
b:set(string)
把 buffer 内容设置为给定字符串。
local b = buffer.new()
b:set("hello")
print(tostring(b))如果启用了 FFI,也可以传入 cdata 指针和长度:
local ffi = require("ffi")
local buffer = require("string.buffer")
local bytes = ffi.new("uint8_t[3]", { 65, 66, 67 })
local b = buffer.new()
b:set(bytes, 3)
print(tostring(b)) -- ABCb:encode(value)
把 Lua 值序列化并追加到当前 buffer。
local b = buffer.new()
b:encode({ ok = true })b:decode()
从当前 buffer 读取并反序列化一个 Lua 值。
local b = buffer.new()
b:encode({ ok = true })
local value = b:decode()
print(value.ok)b:putcdata(ptr, len)
把 FFI cdata 指针指向的内存复制到 buffer。
local ffi = require("ffi")
local buffer = require("string.buffer")
local bytes = ffi.new("uint8_t[3]", { 65, 66, 67 })
local b = buffer.new()
b:putcdata(bytes, 3)
print(tostring(b))b:reserve(size)
预留写入空间,返回指针和可写容量。
local ffi = require("ffi")
local buffer = require("string.buffer")
local b = buffer.new()
local ptr, size = b:reserve(16)
ptr[0] = 65
ptr[1] = 66
ptr[2] = 67
b:commit(3)
print(tostring(b)) -- ABCb:commit(size)
提交通过 reserve 写入的字节数。
如果 size 大于剩余可写容量,会报数值范围错误。
b:ref()
返回当前可读区域的指针和长度。
local ptr, len = b:ref()
print(ptr, len)WARNING
ref() 返回的是 buffer 内部内存引用。后续写入、重置、释放或 GC 都可能让指针失效。
tostring(b)
返回 buffer 当前可读内容。
#b
返回 buffer 当前可读长度。
local b = buffer.new()
b:put("hello")
print(#b)元方法
buffer 对象提供这些元方法:
__gc__tostring__len__index__metatable
典型用法
#高效拼接字符串
local buffer = require("string.buffer")
local b = buffer.new()
for i = 1, 1000 do
b:put("line ", i, "\n")
end
local text = tostring(b)#分段解析数据
local buffer = require("string.buffer")
local b = buffer.new()
b:put("HEAD", "BODY")
local head = b:get(4)
local body = b:get()
print(head, body)#序列化 Lua 值
local buffer = require("string.buffer")
local payload = buffer.encode({
type = "message",
body = "hello"
})
local decoded = buffer.decode(payload)
print(decoded.type, decoded.body)math 库
常量
math.pimath.hugemath.maxintegermath.mininteger
其中:
math.pi是圆周率math.huge表示一个极大值math.maxinteger是9007199254740992,即2^53math.mininteger是-9007199254740992
常用函数
#math.abs(x)
绝对值。
#math.ceil(x)
向上取整。
#math.floor(x)
向下取整。
#math.round(x)
四舍五入。
#math.trunc(x)
截断小数部分,朝零方向取整。
#math.max(x, ...)
返回最大值。
#math.min(x, ...)
返回最小值。
#math.sqrt(x)
平方根。
#math.cbrt(x)
立方根。
#math.pow(x, y)
幂运算。也可以直接用 x ^ y。
#math.fmod(x, y)
浮点取模。
#math.ldexp(x, exp)
返回 x * 2^exp。
#math.sin(x), math.cos(x), math.tan(x)
三角函数。
#math.asin(x), math.acos(x), math.atan(x)
反三角函数。
#math.atan2(y, x)
双参数反正切。
#math.sinh(x), math.cosh(x), math.tanh(x)
双曲函数。
#math.rad(x)
角度转弧度。
#math.deg(x)
弧度转角度。
#math.log(x [, base])
对数。
如果提供第二个参数,则按对应底数计算。
print(math.log(8, 2))#math.log10(x)
以 10 为底的对数。
#math.exp(x)
指数函数。
#math.frexp(x)
将数字拆成尾数和指数,返回两个值。
#math.modf(x)
将数字拆成整数部分和小数部分,返回两个值。
local i, f = math.modf(3.25)
print(i, f)#math.hypot(x, y)
返回直角三角形斜边长度,即 sqrt(x*x + y*y) 的稳定版本。
#math.isnan(x)
判断是否为 NaN。
#math.isinf(x)
判断是否为正负无穷。
#math.isfinite(x)
判断是否为有限数。
#math.random() #math.random(n) #math.random(m, n)
随机数。
行为和当前实现一致:
math.random():返回[0, 1]范围内的浮点数math.random(n):返回[1, n]范围内的整数或数值math.random(m, n):返回[m, n]范围内的整数或数值
当参数是整数语义时,LuaJIT 会尽量返回整数语义结果。
print(math.random())
print(math.random(10))
print(math.random(1, 100))#math.randomseed(seed)
设置随机数种子。
当前实现还支持无参数调用:
math.randomseed()无参数时会尝试使用安全随机源为 PRNG 设种;有参数时则使用给定数值。
#math.noise(x [, y [, z]])
Perlin noise 函数。
支持三种形式:
math.noise(x)math.noise(x, y)math.noise(x, y, z)
如果只传 x 和 z 而中间 y 为 nil,实现里也会按特定分支处理。
print(math.noise(0.1))
print(math.noise(0.1, 0.2))
print(math.noise(0.1, 0.2, 0.3))#math.clamp(x, min, max)
把数值限制在区间 [min, max] 内。
print(math.clamp(20, 0, 10)) -- 10WARNING
当前实现要求 max >= min,否则会报错:max must be greater than or equal to min。
#math.sign(x)
返回数值符号,通常用于区分正数、负数和零。
#math.map(x, inMin, inMax, outMin, outMax)
将数值从一个区间线性映射到另一个区间。
print(math.map(5, 0, 10, 0, 100)) -- 50#math.lerp(a, b, t)
线性插值。
print(math.lerp(0, 10, 0.25)) -- 2.5#math.tointeger(x)
如果 x 在当前运行时的“安全整数”范围内,且本身没有小数部分,则返回该整数;否则返回 nil。
在当前实现中,安全范围是:
-9007199254740992 .. 9007199254740992print(math.tointeger(12)) -- 12
print(math.tointeger(12.5)) -- nil#math.type(x)
返回:
"integer":在安全整数范围内且没有小数部分"float":其余数字nil:非数字
print(math.type(12)) -- integer
print(math.type(12.5)) -- float#math.ult(n, m)
按无符号整数语义比较两个整数,判断 n < m 是否成立。
这个函数适合处理需要“无符号顺序”语义的整数比较场景。
io 库
io 库用于文件读写。取决于 Android 文件权限和宿主提供的可访问目录。
io.open(filename [, mode])
打开文件。
local file = assert(io.open(activity.getLuaPath("config.json"), "r"))
local content = file:read("*a")
file:close()io.input([file])
设置默认输入文件。
io.output([file])
设置默认输出文件。
io.read(...)
从默认输入流读取。
io.write(...)
向默认输出流写入。
io.flush()
刷新输出缓冲。
io.close([file])
关闭文件。
io.lines([filename])
逐行读取文件。
for line in io.lines(activity.getLuaPath("list.txt")) do
print(line)
end文件对象方法
io.open 返回的文件对象常用方法有:
file:read(...)file:write(...)file:flush()file:close()file:seek([whence [, offset]])file:lines()
os 库
os 库提供时间、文件和部分宿主环境相关能力。以下内容根据 /Users/zhuhecun/CLionProjects/LuaJIT-ARM64-only/src/lib_os.c 整理,而不是泛泛按标准 Lua 猜测。
WARNING
LuaJIT 运行时实现支持某个 os.* 函数,不等于它在 Android 宿主里就一定适合作为应用主流程能力。像 os.execute、os.exit 这种接口,在移动端通常都要慎用。
os.clock()
返回 CPU 时间或高精度耗时值,适合测量耗时。
local start = os.clock()
for i = 1, 100000 do end
print(os.clock() - start)os.time([table])
返回 Unix 时间戳。
无参数时返回当前时间:
print(os.time())传入 table 时,会读取这些字段:
sec,默认0min,默认0hour,默认12day,必填month,必填year,必填isdst,可选
local ts = os.time({
year = 2026,
month = 5,
day = 4,
hour = 12,
min = 0,
sec = 0
})
print(ts)如果时间无效,当前实现会返回 nil。
os.date([format [, time]])
将时间戳格式化为字符串或表。
当前实现支持:
- 默认格式
%c - 前缀
!表示按 UTC 处理 *t返回时间字段表- 空格式串返回空字符串
print(os.date("%Y-%m-%d %H:%M:%S"))
print(os.date("!%Y-%m-%dT%H:%M:%SZ"))使用 *t:
local t = os.date("*t")
print(t.year, t.month, t.day, t.hour, t.min, t.sec)*t 返回字段:
secminhourdaymonthyearwdayydayisdst
print(os.date("%Y-%m-%d %H:%M:%S"))os.difftime(t2, t1)
计算两个时间戳差值,返回秒数。
第二个参数默认是 0。
print(os.difftime(os.time(), 0))os.getenv(name)
读取环境变量。
print(os.getenv("HOME"))如果运行目标是控制台受限平台,当前实现可能总是返回 nil。在 Android 应用里,也通常不把它当作主要配置来源。
os.execute(command)
执行外部命令。
当前实现行为取决于编译开关:
- 如果启用了
LJ_NO_SYSTEM,Lua 5.1 兼容路径下会直接返回-1 - 否则会调用底层
system(command)
local status = os.execute("echo hello")
print(status)WARNING
在嵌入式 Android 环境里通常不建议依赖 os.execute。很多场景下它不可用、行为受限,或不符合应用沙箱模型。
os.remove(filename)
删除文件,成功与否按 luaL_fileresult 语义返回。
local ok, err = os.remove(activity.getLuaPath("tmp.txt"))
print(ok, err)os.rename(oldname, newname)
重命名文件,成功与否按 luaL_fileresult 语义返回。
local ok, err = os.rename("a.txt", "b.txt")
print(ok, err)os.tmpname()
生成临时文件名。
在 POSIX 路径下,当前实现使用:
/tmp/lua_XXXXXX并通过 mkstemp 创建唯一文件名。
os.sleep(ms)
让当前线程休眠指定毫秒数。
print("before")
os.sleep(500)
print("after")特点:
- 参数单位是毫秒,不是秒
- 小于
0会被当作0 - 内部使用
nanosleep - 如果被信号中断,会继续补睡剩余时间
WARNING
在 UI 线程里调用 os.sleep 会阻塞界面。它适合工具脚本、后台逻辑或明确可阻塞的上下文,不适合直接放在前台交互主路径。
os.setlocale(locale [, category])
设置或查询当前区域设置。
支持的分类包括:
"ctype""numeric""time""collate""monetary""all"
print(os.setlocale(nil, "time"))
print(os.setlocale("C", "numeric"))如果第一个参数传 nil,通常表示查询当前 locale 而不修改。
os.exit([codeOrBool [, close]])
退出当前进程。
当前实现支持两种第一参数形式:
- 布尔值:
true表示成功退出,false表示失败退出 - 整数:作为退出码
第二个参数为真时,会先 lua_close(L) 再退出。
-- os.exit(0)
-- os.exit(true)DANGER
在 Android 应用中几乎不应该主动调用 os.exit。它会直接结束进程,不符合正常的移动应用生命周期模型。
debug 库
调试库适合开发和排错,不建议在高频热路径中重度使用。
debug.traceback([thread,] [message [, level]])
返回堆栈信息。
print(debug.traceback("something failed", 2))debug.getinfo(f [, what])
读取函数或调用帧信息。
debug.getlocal(thread, level, local)
读取局部变量。
debug.setlocal(thread, level, local, value)
设置局部变量。
debug.getupvalue(f, up)
读取 upvalue。
debug.setupvalue(f, up, value)
设置 upvalue。
debug.sethook([thread,] hook, mask [, count])
注册调试钩子。
debug.getmetatable(value)
获取元表。
debug.setmetatable(value, table)
设置元表。
WARNING
debug 库有很强的反射和运行时改写能力。生产代码里应谨慎使用,特别是在你希望脚本环境更可控时。
package 库
模块系统核心库。
require(name)
加载模块。如果模块已经加载过,则直接返回缓存结果。
local json = require("cjson")package.path
Lua 模块搜索路径。
print(package.path)package.cpath
C 模块搜索路径。
print(package.cpath)package.loaded
模块缓存表。
package.loaded["modules.log"] = nil
local log = require("modules.log")package.preload
预加载模块表。
package.loadlib(libname, funcname)
从动态库中加载导出函数。
local open = package.loadlib("/path/to/libdemo.so", "luaopen_demo")package.searchpath(name, path [, sep [, rep]])
按路径模板查找模块文件。
local file, err = package.searchpath("modules.log", package.path)
print(file, err)utf8 库
LuaJIT 当前集成中包含 utf8 库,用来处理 UTF-8 文本。
utf8.len(s [, i [, j]])
返回 UTF-8 码点数量。
print(utf8.len("你好"))utf8.codepoint(s [, i [, j]])
返回一个或多个码点值。
utf8.char(...)
由码点构造 UTF-8 字符串。
utf8.codes(s)
返回遍历 UTF-8 字符串的迭代器。
for pos, code in utf8.codes("Hi!") do
print(pos, code)
endutf8.offset(s, n [, i])
返回指定码点的字节偏移。
bit 库
LuaJIT 内置高性能位运算库。
bit.band(...)
按位与。
bit.bor(...)
按位或。
bit.bxor(...)
按位异或。
bit.bnot(x)
按位非。
bit.lshift(x, n)
左移。
bit.rshift(x, n)
逻辑右移。
bit.arshift(x, n)
算术右移。
bit.rol(x, n)
循环左移。
bit.ror(x, n)
循环右移。
bit.tohex(x [, n])
转十六进制字符串。
print(bit.tohex(255, 2))bit.tobit(x)
将数字归一到 32 位有符号整数语义。
jit 库
jit 是 LuaJIT 专有库,用于查看和控制 JIT 状态。
jit.on([func|true [, recursive]])
启用 JIT。
jit.off([func|true [, recursive]])
关闭 JIT。
jit.flush([func|true])
清空编译缓存。
jit.status()
查看 JIT 状态。
print(jit.status())jit.versionjit.osjit.arch
返回 LuaJIT 版本、操作系统和 CPU 架构信息。
print(jit.version, jit.os, jit.arch)更详细内容见 JIT 文档。
ffi 库
ffi 是 LuaJIT 最强的扩展能力之一,可以直接声明并调用 C 接口。
ffi.cdef(code)
声明 C 类型、结构体和函数。
local ffi = require("ffi")
ffi.cdef[[
int abs(int x);
]]ffi.load(name [, global])
加载动态库。
local ffi = require("ffi")
local libc = ffi.C
print(libc.abs(-10))ffi.new(ct [, ...])
创建 C 数据对象。
ffi.typeof(ct)
获取 C 类型对象。
ffi.cast(ct, value)
强制类型转换。
ffi.string(ptr [, len])
把 C 字符串或字节缓冲区转成 Lua 字符串。
ffi.sizeof(ct [, nelem])
返回类型或对象大小。
ffi.alignof(ct)
返回类型对齐大小。
ffi.offsetof(ct, field)
返回结构体字段偏移。
ffi.istype(ct, obj)
判断对象是否属于指定 C 类型。
ffi.metatype(ct, metatable)
为 C 类型绑定元表。
WARNING
ffi 直接操作原生内存。类型声明错误、悬空指针、生命周期管理错误都可能导致进程崩溃。
更详细内容见 FFI 文档。
环境补充
除了 LuaJIT 标准库,还会额外提供一些宿主能力:
- 全局
activity - 全局
this - 全局
luakt - 重写后的
print require "import"后得到import、loadlayout、loadbitmap
这些不属于 LuaJIT 标准库,但在 AsLua 里属于高频能力。
常见问题
LuaJIT 和 Lua 5.1 标准库完全一样吗?
不完全一样。LuaJIT 在兼容 Lua 5.1 的基础上增加了 bit、jit、ffi 等能力,也可能在实现细节和性能表现上有所不同。
为什么我能用 print,但行为和普通 Lua 不一样?
因为 AsLua 在初始化时用 LuaPrint 注册并覆盖了 print,它会输出到 AsLua 界面而不是普通终端。
os.execute 在 Android 上靠谱吗?
通常不建议依赖。移动端应用沙箱、权限模型和系统差异会让它变得不稳定或不可用。
该优先使用 ffi 还是 luakt?
在 AsLua 里一般优先使用 luakt 访问 Java / Kotlin API;只有在你明确需要直接调用 C 动态库或处理原生内存时再考虑 ffi。