Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

操作 Table

Table 是 Lua 唯一的数据结构,掌握 C API 中的 table 操作至关重要。

创建 Table

lua_newtable(L);           // 等价于 lua_createtable(L, 0, 0) 
lua_createtable(L, narr, nrec);  // 预分配数组部分 narr、哈希部分 nrec 

读写字段

假设栈顶是一个 table:

// 读:t[key] 
lua_pushstring(L, "name");     // 压入 key 
lua_gettable(L, -2);           // 查询,弹出 key,结果压栈 
// 此时栈顶是 t["name"] 的值 

// 写:t[key] = value 
lua_pushstring(L, "name");
lua_pushstring(L, "Alice");
lua_settable(L, -3);           // 弹出 key 和 value,设置到 table 

lua_gettablelua_settable 会触发 __index / __newindex 元方法。

便捷 API(不触发元方法)

操作函数说明
获取整数键值lua_geti(L, idx, n)t[n],结果压栈
设置整数键值lua_seti(L, idx, n)t[n] = value
获取字符串键值lua_getfield(L, idx, k)t.k,结果压栈
设置字符串键值lua_setfield(L, idx, k, v)t.k = v
原始获取lua_rawget / lua_rawgeti / lua_rawgetp绕过元方法
原始设置lua_rawset / lua_rawseti / lua_rawsetp绕过元方法

遍历 Table

lua_pushnil(L);   // 第一个 key 
while (lua_next(L, table_index) != 0) {
        // 此时栈顶:value (-1), key (-2) 
        // 处理 key-value... 

    lua_pop(L, 1);       // 弹出 value,保留 key 供下一次迭代 
}

lua_next 会触发 __pairs metamethod(如果存在)。如果需要原始遍历,用 lua_rawlen +

整数下标遍历数组部分,或使用 luaH_next 的内部逻辑(不推荐)。

数组长度

lua_Integer len = luaL_len(L, -1);   // 调用 #t,触发 __len 
size_t rawlen = lua_rawlen(L, -1);   // 不触发元方法 

完整代码


#include <assert.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    lua_newtable(L);

    lua_pushstring(L, "Alice");
    lua_setfield(L, -2, "name");
    lua_pushinteger(L, 30);
    lua_setfield(L, -2, "age");

    lua_pushstring(L, "lua");
    lua_seti(L, -2, 1);
    lua_pushstring(L, "c");
    lua_seti(L, -2, 2);

    lua_getfield(L, -1, "name");
    assert(strcmp(lua_tostring(L, -1), "Alice") == 0);
    lua_pop(L, 1);

    lua_geti(L, -1, 1);
    assert(strcmp(lua_tostring(L, -1), "lua") == 0);
    lua_pop(L, 1);

    assert(luaL_len(L, -1) == 2);

    lua_rawgeti(L, -1, 1);
    assert(strcmp(lua_tostring(L, -1), "lua") == 0);
    lua_pop(L, 1);

    lua_pop(L, 1);

    lua_close(L);
    puts("05-tables: ok");
    return 0;
}