Skip to content

标准库

LuaJIT 提供一组默认可用的标准库,用于处理字符串、表、协程、数学计算、文件、时间、调试和模块加载

全局函数

这些函数不属于某个命名库,可以直接调用。

assert(v [, message])

断言 v 为真值,否则抛出错误。

lua
local file = io.open("config.json", "r")
assert(file, "config.json not found")

error(message [, level])

抛出一个 Lua 错误。

lua
local function requireString(value)
  if type(value) ~= "string" then
    error("expected string", 2)
  end
end

getmetatable(value)

获取对象元表。

lua
local mt = getmetatable({})
print(mt)

setmetatable(table, metatable)

设置表的元表。

lua
local mt = {
  __index = function()
    return "default"
  end
}

local t = setmetatable({}, mt)
print(t.name)

ipairs(table)

按整数索引 1..n 顺序遍历数组部分。

lua
for index, value in ipairs({ "a", "b", "c" }) do
  print(index, value)
end

pairs(table)

遍历表中的所有键值对。

lua
for key, value in pairs({ name = "AsLua", runtime = "LuaJIT" }) do
  print(key, value)
end

next(table [, index])

pairs 底层使用的原语,用于迭代表。

pcall(f, ...)

保护调用,失败时不直接中断脚本。

lua
local ok, result = pcall(function()
  return require("missing")
end)

print(ok, result)

xpcall(f, err)

带错误处理函数的保护调用,常配合 debug.traceback 使用。

lua
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 的日志界面中。

lua
print("Hello AsLua")

rawequal(a, b)

绕过 __eq 元方法,直接比较两个值。

rawget(table, key)

绕过 __index 直接读取字段。

rawset(table, key, value)

绕过 __newindex 直接写入字段。

rawlen(value)

返回对象原始长度,不触发元方法。

select(index, ...)

获取可变参数中的某一部分。

lua
local function demo(...)
  print(select("#", ...))
  print(select(2, ...))
end

demo("a", "b", "c")

tonumber(value [, base])

转换为数字。

lua
print(tonumber("42"))
print(tonumber("ff", 16))

tostring(value)

转换为字符串。对 Java 对象来说,AsLua 里更常见的是 luakt.tostring(obj),但普通 Lua 值仍然直接使用 tostring

type(value)

返回值类型:

  • nil
  • boolean
  • number
  • string
  • table
  • function
  • userdata
  • thread

unpack(list [, i [, j]])

将数组元素展开为多个返回值。

lua
local args = { "a", "b", "c" }
print(unpack(args))

loadstring(string [, chunkname])

从字符串加载 Lua 代码。

lua
local fn = assert(loadstring("return 1 + 2"))
print(fn())

loadfile(filename)

从文件加载 Lua 代码。

lua
local fn = assert(loadfile("main.lua"))

dofile(filename)

加载并立刻执行文件。

lua
dofile("bootstrap.lua")

collectgarbage([opt [, arg]])

控制 Lua GC。

lua
collectgarbage("collect")

coroutine

Lua 协程提供协作式并发,不是系统线程。

coroutine.create(f)

创建协程。

lua
local co = coroutine.create(function()
  print("step 1")
  coroutine.yield("pause")
  print("step 2")
end)

coroutine.resume(co [, val1, ...])

恢复执行协程。

lua
local ok, value = coroutine.resume(co)
print(ok, value)

coroutine.yield(...)

挂起当前协程并返回控制权。

coroutine.status(co)

返回协程状态:

  • running
  • suspended
  • normal
  • dead

coroutine.wrap(f)

返回一个包装函数,调用时自动 resume

coroutine.running()

返回当前运行中的协程。

table

table 是 Lua 最重要的数据结构库。

table.insert(list [, pos], value)

插入元素。

lua
local t = { "a", "c" }
table.insert(t, 2, "b")

table.remove(list [, pos])

移除元素并返回被删除的值。

table.concat(list [, sep [, i [, j]]])

拼接字符串数组。

lua
print(table.concat({ "Lua", "JIT" }, "-"))

table.sort(list [, comp])

原地排序。

lua
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]])

查找子串或模式。

lua
local i, j = string.find("hello world", "world")
print(i, j)

string.format(format, ...)

格式化字符串。

lua
print(string.format("id=%04d", 12))

string.gmatch(s, pattern)

返回一个迭代器,遍历所有匹配项。

lua
for word in string.gmatch("a,b,c", "[^,]+") do
  print(word)
end

string.gsub(s, pattern, repl [, n])

替换字符串中的匹配内容。

lua
print(string.gsub("hello world", "world", "LuaJIT"))

string.len(s)

返回字节长度。

string.lower(s)

转小写。

string.upper(s)

转大写。

string.match(s, pattern [, init])

按模式提取内容。

lua
local name = string.match("name=Hello", "name=(.+)")
print(name)

string.rep(s, n)

重复字符串。

string.reverse(s)

反转字符串。

string.sub(s, i [, j])

截取子串。

lua
print(string.sub("abcdef", 2, 4))

string.dump(function)

导出函数的字节码表示。

WARNING

字节码与运行时实现相关,通常只在工具链、缓存或调试场景下使用。

buffer

它提供可变字符串缓冲区,适合高频拼接、分段读取、二进制写入和 Lua 值序列化。

通常这样加载:

lua
local buffer = require("string.buffer")

TIP

多数缓冲区方法会返回 buffer 自身,因此可以链式调用。

lua
local b = buffer.new()

b:put("Hello", " ", "AsLua")
print(tostring(b))

buffer.new([size] [, options])

创建新的 buffer。

lua
local b1 = buffer.new()
local b2 = buffer.new(1024)

第一个参数可以是预分配大小。如果提供 options table,可以传入:

  • dict
  • metatable

它们用于 encode / decode 的字典与元表序列化配置。

也可以只传 options:

lua
local b = buffer.new({
  dict = {}
})

buffer.encode(value)

把 Lua 值序列化为字符串。

lua
local payload = buffer.encode({
  name = "AsLua",
  runtime = "LuaJIT"
})

buffer.decode(string)

buffer.encode 生成的字符串反序列化为 Lua 值。

lua
local value = buffer.decode(payload)
print(value.name)

b:put(...)

向 buffer 追加多个值。

支持:

  • 字符串
  • 整数
  • 浮点数
  • 另一个 buffer
  • __tostring 元方法的对象
lua
local b = buffer.new()
b:put("id=", 1001, ", name=", "AsLua")
print(tostring(b))

WARNING

不能把 buffer 自己追加到自己,否则会报错。

b:putf(format, ...)

按格式化规则写入内容。

lua
local b = buffer.new()
b:putf("id=%04d name=%s", 12, "AsLua")
print(tostring(b))

b:get([n1 [, n2 ...]])

从当前读指针读取内容,并推进读指针。

无参数时等同于读取剩余全部内容:

lua
local b = buffer.new()
b:put("abcdef")

print(b:get(2)) -- ab
print(b:get(2)) -- cd
print(b:get())  -- ef

一次传多个长度会返回多个字符串:

lua
local b = buffer.new()
b:put("abcdef")

local a, c = b:get(2, 4)
print(a, c)

b:skip(n)

跳过 n 个字节。

lua
local b = buffer.new()
b:put("abcdef")
b:skip(2)
print(b:get()) -- cdef

b:reset()

重置 buffer 内容,并返回 buffer 自身。

b:free()

释放 buffer 内部存储,并返回 buffer 自身。

b:set(string)

把 buffer 内容设置为给定字符串。

lua
local b = buffer.new()
b:set("hello")
print(tostring(b))

如果启用了 FFI,也可以传入 cdata 指针和长度:

lua
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)) -- ABC

b:encode(value)

把 Lua 值序列化并追加到当前 buffer。

lua
local b = buffer.new()
b:encode({ ok = true })

b:decode()

从当前 buffer 读取并反序列化一个 Lua 值。

lua
local b = buffer.new()
b:encode({ ok = true })

local value = b:decode()
print(value.ok)

b:putcdata(ptr, len)

把 FFI cdata 指针指向的内存复制到 buffer。

lua
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)

预留写入空间,返回指针和可写容量。

lua
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)) -- ABC

b:commit(size)

提交通过 reserve 写入的字节数。

如果 size 大于剩余可写容量,会报数值范围错误。

b:ref()

返回当前可读区域的指针和长度。

lua
local ptr, len = b:ref()
print(ptr, len)

WARNING

ref() 返回的是 buffer 内部内存引用。后续写入、重置、释放或 GC 都可能让指针失效。

tostring(b)

返回 buffer 当前可读内容。

#b

返回 buffer 当前可读长度。

lua
local b = buffer.new()
b:put("hello")
print(#b)

元方法

buffer 对象提供这些元方法:

  • __gc
  • __tostring
  • __len
  • __index
  • __metatable

典型用法

#高效拼接字符串

lua
local buffer = require("string.buffer")
local b = buffer.new()

for i = 1, 1000 do
  b:put("line ", i, "\n")
end

local text = tostring(b)

#分段解析数据

lua
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 值

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.pi
  • math.huge
  • math.maxinteger
  • math.mininteger

其中:

  • math.pi 是圆周率
  • math.huge 表示一个极大值
  • math.maxinteger9007199254740992,即 2^53
  • math.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])

对数。

如果提供第二个参数,则按对应底数计算。

lua
print(math.log(8, 2))

#math.log10(x)

以 10 为底的对数。

#math.exp(x)

指数函数。

#math.frexp(x)

将数字拆成尾数和指数,返回两个值。

#math.modf(x)

将数字拆成整数部分和小数部分,返回两个值。

lua
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 会尽量返回整数语义结果。

lua
print(math.random())
print(math.random(10))
print(math.random(1, 100))

#math.randomseed(seed)

设置随机数种子。

当前实现还支持无参数调用:

lua
math.randomseed()

无参数时会尝试使用安全随机源为 PRNG 设种;有参数时则使用给定数值。

#math.noise(x [, y [, z]])

Perlin noise 函数。

支持三种形式:

  • math.noise(x)
  • math.noise(x, y)
  • math.noise(x, y, z)

如果只传 xz 而中间 ynil,实现里也会按特定分支处理。

lua
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] 内。

lua
print(math.clamp(20, 0, 10)) -- 10

WARNING

当前实现要求 max >= min,否则会报错:max must be greater than or equal to min

#math.sign(x)

返回数值符号,通常用于区分正数、负数和零。

#math.map(x, inMin, inMax, outMin, outMax)

将数值从一个区间线性映射到另一个区间。

lua
print(math.map(5, 0, 10, 0, 100)) -- 50

#math.lerp(a, b, t)

线性插值。

lua
print(math.lerp(0, 10, 0.25)) -- 2.5

#math.tointeger(x)

如果 x 在当前运行时的“安全整数”范围内,且本身没有小数部分,则返回该整数;否则返回 nil

在当前实现中,安全范围是:

txt
-9007199254740992 .. 9007199254740992
lua
print(math.tointeger(12))     -- 12
print(math.tointeger(12.5))   -- nil

#math.type(x)

返回:

  • "integer":在安全整数范围内且没有小数部分
  • "float":其余数字
  • nil:非数字
lua
print(math.type(12))    -- integer
print(math.type(12.5))  -- float

#math.ult(n, m)

按无符号整数语义比较两个整数,判断 n < m 是否成立。

这个函数适合处理需要“无符号顺序”语义的整数比较场景。

io

io 库用于文件读写。取决于 Android 文件权限和宿主提供的可访问目录。

io.open(filename [, mode])

打开文件。

lua
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])

逐行读取文件。

lua
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.executeos.exit 这种接口,在移动端通常都要慎用。

os.clock()

返回 CPU 时间或高精度耗时值,适合测量耗时。

lua
local start = os.clock()
for i = 1, 100000 do end
print(os.clock() - start)

os.time([table])

返回 Unix 时间戳。

无参数时返回当前时间:

lua
print(os.time())

传入 table 时,会读取这些字段:

  • sec,默认 0
  • min,默认 0
  • hour,默认 12
  • day,必填
  • month,必填
  • year,必填
  • isdst,可选
lua
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 返回时间字段表
  • 空格式串返回空字符串
lua
print(os.date("%Y-%m-%d %H:%M:%S"))
print(os.date("!%Y-%m-%dT%H:%M:%SZ"))

使用 *t

lua
local t = os.date("*t")
print(t.year, t.month, t.day, t.hour, t.min, t.sec)

*t 返回字段:

  • sec
  • min
  • hour
  • day
  • month
  • year
  • wday
  • yday
  • isdst
lua
print(os.date("%Y-%m-%d %H:%M:%S"))

os.difftime(t2, t1)

计算两个时间戳差值,返回秒数。

第二个参数默认是 0

lua
print(os.difftime(os.time(), 0))

os.getenv(name)

读取环境变量。

lua
print(os.getenv("HOME"))

如果运行目标是控制台受限平台,当前实现可能总是返回 nil。在 Android 应用里,也通常不把它当作主要配置来源。

os.execute(command)

执行外部命令。

当前实现行为取决于编译开关:

  • 如果启用了 LJ_NO_SYSTEM,Lua 5.1 兼容路径下会直接返回 -1
  • 否则会调用底层 system(command)
lua
local status = os.execute("echo hello")
print(status)

WARNING

在嵌入式 Android 环境里通常不建议依赖 os.execute。很多场景下它不可用、行为受限,或不符合应用沙箱模型。

os.remove(filename)

删除文件,成功与否按 luaL_fileresult 语义返回。

lua
local ok, err = os.remove(activity.getLuaPath("tmp.txt"))
print(ok, err)

os.rename(oldname, newname)

重命名文件,成功与否按 luaL_fileresult 语义返回。

lua
local ok, err = os.rename("a.txt", "b.txt")
print(ok, err)

os.tmpname()

生成临时文件名。

在 POSIX 路径下,当前实现使用:

txt
/tmp/lua_XXXXXX

并通过 mkstemp 创建唯一文件名。

os.sleep(ms)

让当前线程休眠指定毫秒数。

lua
print("before")
os.sleep(500)
print("after")

特点:

  • 参数单位是毫秒,不是秒
  • 小于 0 会被当作 0
  • 内部使用 nanosleep
  • 如果被信号中断,会继续补睡剩余时间

WARNING

在 UI 线程里调用 os.sleep 会阻塞界面。它适合工具脚本、后台逻辑或明确可阻塞的上下文,不适合直接放在前台交互主路径。

os.setlocale(locale [, category])

设置或查询当前区域设置。

支持的分类包括:

  • "ctype"
  • "numeric"
  • "time"
  • "collate"
  • "monetary"
  • "all"
lua
print(os.setlocale(nil, "time"))
print(os.setlocale("C", "numeric"))

如果第一个参数传 nil,通常表示查询当前 locale 而不修改。

os.exit([codeOrBool [, close]])

退出当前进程。

当前实现支持两种第一参数形式:

  • 布尔值:true 表示成功退出,false 表示失败退出
  • 整数:作为退出码

第二个参数为真时,会先 lua_close(L) 再退出。

lua
-- os.exit(0)
-- os.exit(true)

DANGER

在 Android 应用中几乎不应该主动调用 os.exit。它会直接结束进程,不符合正常的移动应用生命周期模型。

debug

调试库适合开发和排错,不建议在高频热路径中重度使用。

debug.traceback([thread,] [message [, level]])

返回堆栈信息。

lua
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)

加载模块。如果模块已经加载过,则直接返回缓存结果。

lua
local json = require("cjson")

package.path

Lua 模块搜索路径。

lua
print(package.path)

package.cpath

C 模块搜索路径。

lua
print(package.cpath)

package.loaded

模块缓存表。

lua
package.loaded["modules.log"] = nil
local log = require("modules.log")

package.preload

预加载模块表。

package.loadlib(libname, funcname)

从动态库中加载导出函数。

lua
local open = package.loadlib("/path/to/libdemo.so", "luaopen_demo")

package.searchpath(name, path [, sep [, rep]])

按路径模板查找模块文件。

lua
local file, err = package.searchpath("modules.log", package.path)
print(file, err)

utf8

LuaJIT 当前集成中包含 utf8 库,用来处理 UTF-8 文本。

utf8.len(s [, i [, j]])

返回 UTF-8 码点数量。

lua
print(utf8.len("你好"))

utf8.codepoint(s [, i [, j]])

返回一个或多个码点值。

utf8.char(...)

由码点构造 UTF-8 字符串。

utf8.codes(s)

返回遍历 UTF-8 字符串的迭代器。

lua
for pos, code in utf8.codes("Hi!") do
  print(pos, code)
end

utf8.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])

转十六进制字符串。

lua
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 状态。

lua
print(jit.status())

jit.versionjit.osjit.arch

返回 LuaJIT 版本、操作系统和 CPU 架构信息。

lua
print(jit.version, jit.os, jit.arch)

更详细内容见 JIT 文档

ffi

ffi 是 LuaJIT 最强的扩展能力之一,可以直接声明并调用 C 接口。

ffi.cdef(code)

声明 C 类型、结构体和函数。

lua
local ffi = require("ffi")

ffi.cdef[[
int abs(int x);
]]

ffi.load(name [, global])

加载动态库。

lua
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" 后得到 importloadlayoutloadbitmap

这些不属于 LuaJIT 标准库,但在 AsLua 里属于高频能力。

常见问题

LuaJIT 和 Lua 5.1 标准库完全一样吗?

不完全一样。LuaJIT 在兼容 Lua 5.1 的基础上增加了 bitjitffi 等能力,也可能在实现细节和性能表现上有所不同。

为什么我能用 print,但行为和普通 Lua 不一样?

因为 AsLua 在初始化时用 LuaPrint 注册并覆盖了 print,它会输出到 AsLua 界面而不是普通终端。

os.execute 在 Android 上靠谱吗?

通常不建议依赖。移动端应用沙箱、权限模型和系统差异会让它变得不稳定或不可用。

该优先使用 ffi 还是 luakt

在 AsLua 里一般优先使用 luakt 访问 Java / Kotlin API;只有在你明确需要直接调用 C 动态库或处理原生内存时再考虑 ffi