标准库

       本节将深入解析Lua所有标准库的API设计、实现原理、使用场景以及在Android平台的特殊适配和优化技巧。

1. 基础库

1.1 核心函数

-- 类型检查与转换
assert(type("") == "string")  -- 类型判断
local n = tonumber("42")      -- 安全转换
local s = tostring({})       -- 输出table地址

-- 环境控制
local env = {print=print}
setmetatable(env, {__index=_G})
setfenv(1, env)  -- 修改当前环境

-- 元编程
local t = {}
debug.setmetatable(t, {__call=function() print("called!") end})
t()  -- 输出"called!"

关键机制:

1.2 模块系统

-- 模块加载优化
package.preload.mymod = function()
    return {version="1.0"}  -- 预加载模块
end

-- 搜索路径配置
package.path = package.path..";/data/data/com.example/files/?.lua"

-- 自定义加载器
table.insert(package.searchers, function(modname)
    local asset = "lua/"..modname:gsub("%.", "/")..".lua"
    if android.assetExists(asset) then
        return load(android.readAsset(asset), modname)
    end
end)

Android适配:

2. 字符串处理

2.1 模式匹配

-- Unicode安全处理
local function utf8len(s)
    return select(2, s:gsub("[^\128-\193]", ""))
end

-- 模式匹配优化
local log = "ERR|2023-01-01|Invalid param|user=123"
local typ, date, msg = log:match("^(%a+)|([^|]+)|(.+)")

-- 高效字符串构建
local buf = {}
for i = 1, 100 do
    buf[i] = "line"..i
end
local str = table.concat(buf, "\n")

性能陷阱:

2.2 二进制处理

-- 使用string.pack/unpack(5.3+)
local bin = string.pack(">i4 i2", 123456, 789)
local num, short = string.unpack(">i4 i2", bin)

-- 与Java交互
local ByteBuffer = luajava.bindClass("java.nio.ByteBuffer")
local bb = ByteBuffer.wrap(luajava.byteArray(bin))
bb:order(ByteBuffer.BIG_ENDIAN)
local intVal = bb:getInt()

跨平台注意:

3. 表与数组

3.1 高级操作

-- 表克隆实现
local function clone(t, deep)
    local copy = {}
    for k, v in pairs(t) do
        if deep and type(v) == "table" then
            copy[k] = clone(v, true)
        else
            copy[k] = v
        end
    end
    return copy
end

-- 数组去重
local function uniq(arr)
    local seen, res = {}, {}
    for _, v in ipairs(arr) do
        if not seen[v] then
            table.insert(res, v)
            seen[v] = true
        end
    end
    return res
end

优化技巧:

3.2 元表编程

-- 只读表实现
local function readonly(t)
    return setmetatable({}, {
        __index = t,
        __newindex = function() error("readonly table") end,
        __metatable = false
    })
end

-- 默认值表
local defaults = {color="red", size=10}
local mt = {
    __index = function(t, k)
        return defaults[k]
    end
}
local config = setmetatable({color="blue"}, mt)

设计模式:

4. 文件与I/O

4.1 文件操作

-- 安全文件读写
local function safeWrite(path, data)
    local tmp = path..".tmp"
    local f = assert(io.open(tmp, "wb"))
    f:write(data)
    f:close()
    os.rename(tmp, path)  -- 原子操作
end

-- 遍历目录(Android需通过JNI)
local function scanDir(path)
    local p = io.popen("ls "..path)
    for name in p:lines() do
        print(name)
    end
    p:close()
end

Android限制:

4.2 流处理

-- 缓冲读取器
function lines(filename)
    local f = assert(io.open(filename))
    return function()
        local line = f:read()
        if not line then f:close() end
        return line
    end
end

-- 与Java流互操作
local is = activity.getAssets().open("data.txt")
local reader = luajava.newInstance("java.io.BufferedReader",
                 luajava.newInstance("java.io.InputStreamReader", is))
local line = reader:readLine()  -- Java流读取

混合编程:

5. 操作系统库

5.1 系统交互

-- 平台识别
local isAndroid = package.config:sub(1,1) == "/" 
               and os.getenv("ANDROID_ROOT")

-- 执行命令(Android有限制)
local function exec(cmd)
    local p = io.popen(cmd)
    local output = p:read("*a")
    p:close()
    return output
end

-- 环境变量处理
local function getEnvBool(name)
    local val = os.getenv(name)
    return val and val:lower() == "true"
end

安全警告:

5.2 时间处理

-- 高精度计时
local start = os.clock()
-- do something
print(string.format("耗时: %.2fms", (os.clock()-start)*1000))

-- 日期转换
local t = os.date("*t")
local timestamp = os.time({
    year=2023, month=1, day=1,
    hour=0, min=0, sec=0})

-- Android系统时间
local System = luajava.bindClass("java.lang.System")
local uptime = System:nanoTime() / 1e9

时间规范:

6. 数学库

6.1 数值计算

-- 随机数生成
math.randomseed(os.time())
local dice = math.random(1, 6)

-- 位运算(5.3+)
local flags = 0x01 | 0x04  -- 位或
local mask = flags & 0x05   -- 位与

-- 大整数处理
local MAX_INT32 = 2^31-1
local function safeAdd(a, b)
    if a > MAX_INT32 - b then error("overflow") end
    return a + b
end

数值安全:

6.2 几何计算

-- 坐标转换
local function rotate(x, y, angle)
    local rad = math.rad(angle)
    local cos, sin = math.cos(rad), math.sin(rad)
    return x*cos - y*sin, x*sin + y*cos
end

-- 屏幕适配
local density = activity.getResources().getDisplayMetrics().density
local function dp2px(dp)
    return math.floor(dp * density + 0.5)
end

图形计算:

7. 调试库

7.1 调试接口

-- 获取调用栈
local function callTrace()
    local trace = {}
    for i = 2, 10 do
        local info = debug.getinfo(i, "nSl")
        if not info then break end
        trace[#trace+1] = string.format("%s:%d in %s", 
            info.short_src, info.currentline, info.name or "?")
    end
    return table.concat(trace, "\n")
end

-- 钩子函数
debug.sethook(function(event, line)
    print(event, line)
end, "l")

调试建议:

7.2 性能分析

-- 简单性能分析
local function profile(fn)
    local start = os.clock()
    local count = debug.getinfo(fn, "u").nups
    fn()
    return os.clock() - start, count
end

-- 内存分析
local function memUsage()
    collectgarbage()
    return collectgarbage("count")
end

分析工具:

8. Android扩展库

8.1 平台集成

-- 调用Android API
local Activity = luajava.bindClass("android.app.Activity")
local Context = luajava.bindClass("android.content.Context")

-- 资源访问
local resID = activity.getResources()
            .getIdentifier("icon", "drawable", activity.getPackageName())

-- 线程切换
activity.runOnUiThread(luajava.createProxy("java.lang.Runnable", {
    run = function()
        toast("Hello from UI thread")
    end
}))

交互规范:

8.2 性能敏感操作

-- JNI优化
local jni = luajava.bindClass("com.example.JNIBridge")
local buffer = jni:getDirectBuffer()  -- 避免数据拷贝

-- 对象池模式
local recycler = {
    pool = {},
    get = function(self, cls)
        if #self.pool > 0 then
            return table.remove(self.pool)
        end
        return luajava.new(cls)
    end,
    recycle = function(self, obj)
        table.insert(self.pool, obj)
    end
}

优化原则: