如何在C++中实现对Lua嵌套表的读取与写入操作?
C++实现可修改Lua嵌套表的TimelineEditor函数
Lua向C传递表时默认是引用传递,因此C侧对表的修改会直接同步到Lua侧的原表,无需额外返回值。以下是基于原生Lua C API的实现方案:
1. 核心C++代码实现
依赖头文件
需要引入Lua官方C API头文件:
extern "C" { #include <lua.h> #include <lauxlib.h> #include <lualib.h> } // 若使用C++版Lua头文件可直接引入 #include <lua.hpp>
TimelineEditor函数实现
注册到Lua的C函数必须遵循int(lua_State*)的签名规范:
int TimelineEditor(lua_State* L) { // 校验入参:第一个参数必须为表类型 luaL_checktype(L, 1, LUA_TTABLE); // 遍历外层二维表的每一行 lua_pushnil(L); // 压入初始遍历key while (lua_next(L, 1) != 0) { // 此时栈结构:-2 = 外层表key(行号,从1开始),-1 = 内层行表 if (lua_istable(L, -1)) { // === 示例:读取内层表值 === lua_pushinteger(L, 3); // 压入要读取的索引3 lua_gettable(L, -2); // 等价执行 row[3],结果压入栈顶 int thirdColValue = lua_tointeger(L, -1); lua_pop(L, 1); // 读取完成弹出值,栈恢复原结构 // === 示例:修改内层表值 === lua_pushinteger(L, 4); // 压入要修改的索引4 lua_pushinteger(L, 99); // 压入新值 lua_settable(L, -3); // 等价执行 row[4] = 99,执行后自动弹出key和value // === 示例:给内层表新增自定义字段 === lua_pushstring(L, "modified"); lua_pushboolean(L, 1); lua_settable(L, -3); // 等价执行 row.modified = true } // 弹出当前value,保留key作为下一轮遍历的起点 lua_pop(L, 1); } // === 示例:向外层表新增一行数据 === lua_pushinteger(L, 3); // 新行的索引为3 lua_newtable(L); // 创建新的内层行表 // 给新行填充4个元素 lua_pushinteger(L, 1); lua_pushinteger(L, 12); lua_settable(L, -3); lua_pushinteger(L, 2); lua_pushinteger(L, 34); lua_settable(L, -3); lua_pushinteger(L, 3); lua_pushinteger(L, 56); lua_settable(L, -3); lua_pushinteger(L, 4); lua_pushinteger(L, 78); lua_settable(L, -3); lua_settable(L, 1); // 等价执行 data[3] = 新行表 // 无返回值给Lua,返回0 return 0; }
函数注册
需要在Lua状态机初始化完成后,将C++函数注册到Lua全局环境:
void registerTimelineFunc(lua_State* L) { lua_pushcfunction(L, TimelineEditor); lua_setglobal(L, "TimelineEditor"); }
2. 关键写入操作说明
写入Lua表的核心API是lua_settable,调用要求如下:
- 调用前栈结构从顶到底依次为:
value、key、要操作的表 - 调用后会自动弹出
key和value,栈上只剩下原表,适合遍历场景下连续操作 - Lua数组默认从1开始索引,若使用0作为key会被识别为哈希字段,不属于数组部分
3. 简化方案(基于sol2绑定库)
如果项目使用sol2 Lua绑定库,写法会更简洁直观:
#include <sol/sol.hpp> int TimelineEditor(lua_State* L) { sol::state_view lua(L); sol::table data = lua.get<sol::table>(1); // 直接通过下标读写 data[1][4] = 99; data[1]["modified"] = true; // 新增行 data[3] = sol::as_table(std::vector<int>{12, 34, 56, 78}); return 0; }
4. Lua侧验证
调用TimelineEditor后直接打印原表即可验证修改结果:
local data = { { 44, 34, 0, 7, }, { 4, 4, 1, 3, }, } TimelineEditor(data) print(data[1][4]) -- 输出99 print(data[1].modified) -- 输出true print(data[3][2]) -- 输出34
内容的提问来源于stack exchange,提问作者idbrii
相关产品推荐
相关产品推荐

