操作 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_gettable和lua_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;
}