如何从 C++ 读取和写入嵌套的 lua 表?
How can I read and write to nested lua tables from C++?
我的 lua 代码中有一个嵌套的 table,我想将其传递给 C++,以便本机代码可以对其进行操作:
-- Some persistent data in my game
local data = {
{ 44, 34, 0, 7, },
{ 4, 4, 1, 3, },
}
-- Pass it into a C++ function that can modify the input data.
TimelineEditor(data)
如何编写 C++ 代码来读取嵌套的 table 并修改其值?
Reading Lua nested tables in C++ and lua c read nested tables 都描述了我如何从嵌套的 table 中读取,但没有描述如何写入它们。
简答
Lua 使用堆栈从 table 中获取值。要修改 table 值,您需要使用 lua_rawgeti
推送要修改的 table,使用 lua_pushinteger
推送要插入的值,然后设置值在 table 和 lua_rawseti
.
写这篇文章时,重要的是可视化堆栈以确保您使用正确的索引:
lua_rawgeti()
stack:
table
lua_rawgeti()
stack:
number <-- top of the stack
table
lua_tonumber()
stack:
number
table
lua_pop()
stack:
table
lua_pushinteger()
stack:
number
table
lua_rawseti()
stack:
table
负索引是堆栈位置,正索引是参数位置。所以我们通常会传递 -1 来访问堆栈中的 table。当调用 lua_rawseti
写入 table 时,我们将传递 -2,因为 table 低于我们正在写入的值。
例子
我将添加 inspect.lua 到 lua 代码以打印出 table 值,以便我们可以看到值已修改。
local inspect = require "inspect"
local data = {
{ 44, 34, 0, 7, },
{ 4, 4, 1, 3, },
}
print("BEFORE =", inspect(data, { depth = 5, }))
TimelineEditor(data)
print("AFTER =", inspect(data, { depth = 5, }))
假设您已经弄清楚 BindingCodeToLua,您可以像这样实现函数:
// Replace LOG with whatever you use for logging or use this:
#define LOG(...) printf(__VA_ARGS__); printf("\n")
// I bound with Lunar. I don't think it makes a difference for this example.
int TimelineEditor(lua_State* L)
{
LOG("Read the values and print them out to show that it's working.");
{
int entries_table_idx = 1;
luaL_checktype(L, entries_table_idx, LUA_TTABLE);
int n_entries = static_cast<int>(lua_rawlen(L, entries_table_idx));
LOG("%d entries", n_entries);
for (int i = 1; i <= n_entries; ++i)
{
// Push inner table onto stack.
lua_rawgeti(L, entries_table_idx, i);
int item_table_idx = 1;
luaL_checktype(L, -1, LUA_TTABLE);
int n_items = static_cast<int>(lua_rawlen(L, -1));
LOG("%d items", n_items);
for (int i = 1; i <= n_items; ++i)
{
// Push value from table onto stack.
lua_rawgeti(L, -1, i);
int is_number = 0;
// Read value
int x = static_cast<int>(lua_tonumberx(L, -1, &is_number));
if (!is_number)
{
// fire an error
luaL_checktype(L, -1, LUA_TNUMBER);
}
LOG("Got: %d", x);
// pop value off stack
lua_pop(L, 1);
}
// pop table off stack
lua_pop(L, 1);
}
}
LOG("Overwrite the values");
{
int entries_table_idx = 1;
luaL_checktype(L, entries_table_idx, LUA_TTABLE);
int n_entries = static_cast<int>(lua_rawlen(L, entries_table_idx));
LOG("%d entries", n_entries);
for (int i = 1; i <= n_entries; ++i)
{
// Push inner table onto stack.
lua_rawgeti(L, entries_table_idx, i);
int item_table_idx = 1;
luaL_checktype(L, -1, LUA_TTABLE);
int n_items = static_cast<int>(lua_rawlen(L, -1));
LOG("%d items", n_items);
for (int j = 1; j <= n_items; ++j)
{
int x = j + 10;
// Push new value onto stack.
lua_pushinteger(L, x);
// rawseti pops the value off. Need to go -2 to get to the
// table because the value is on top.
lua_rawseti(L, -2, j);
LOG("Wrote: %d", x);
}
// pop table off stack
lua_pop(L, 1);
}
}
// No return values
return 0;
}
输出:
BEFORE = { { 44, 34, 0, 7 }, { 4, 4, 1, 3 } }
Read the values and print them out to show that it's working.
2 entries
4 items
Got: 44
Got: 34
Got: 0
Got: 7
4 items
Got: 4
Got: 4
Got: 1
Got: 3
Overwrite the values
2 entries
4 items
Wrote: 11
Wrote: 12
Wrote: 13
Wrote: 14
4 items
Wrote: 11
Wrote: 12
Wrote: 13
Wrote: 14
AFTER = { { 11, 12, 13, 14 }, { 11, 12, 13, 14 } }
我的 lua 代码中有一个嵌套的 table,我想将其传递给 C++,以便本机代码可以对其进行操作:
-- Some persistent data in my game
local data = {
{ 44, 34, 0, 7, },
{ 4, 4, 1, 3, },
}
-- Pass it into a C++ function that can modify the input data.
TimelineEditor(data)
如何编写 C++ 代码来读取嵌套的 table 并修改其值?
Reading Lua nested tables in C++ and lua c read nested tables 都描述了我如何从嵌套的 table 中读取,但没有描述如何写入它们。
简答
Lua 使用堆栈从 table 中获取值。要修改 table 值,您需要使用 lua_rawgeti
推送要修改的 table,使用 lua_pushinteger
推送要插入的值,然后设置值在 table 和 lua_rawseti
.
写这篇文章时,重要的是可视化堆栈以确保您使用正确的索引:
lua_rawgeti()
stack:
table
lua_rawgeti()
stack:
number <-- top of the stack
table
lua_tonumber()
stack:
number
table
lua_pop()
stack:
table
lua_pushinteger()
stack:
number
table
lua_rawseti()
stack:
table
负索引是堆栈位置,正索引是参数位置。所以我们通常会传递 -1 来访问堆栈中的 table。当调用 lua_rawseti
写入 table 时,我们将传递 -2,因为 table 低于我们正在写入的值。
例子
我将添加 inspect.lua 到 lua 代码以打印出 table 值,以便我们可以看到值已修改。
local inspect = require "inspect"
local data = {
{ 44, 34, 0, 7, },
{ 4, 4, 1, 3, },
}
print("BEFORE =", inspect(data, { depth = 5, }))
TimelineEditor(data)
print("AFTER =", inspect(data, { depth = 5, }))
假设您已经弄清楚 BindingCodeToLua,您可以像这样实现函数:
// Replace LOG with whatever you use for logging or use this:
#define LOG(...) printf(__VA_ARGS__); printf("\n")
// I bound with Lunar. I don't think it makes a difference for this example.
int TimelineEditor(lua_State* L)
{
LOG("Read the values and print them out to show that it's working.");
{
int entries_table_idx = 1;
luaL_checktype(L, entries_table_idx, LUA_TTABLE);
int n_entries = static_cast<int>(lua_rawlen(L, entries_table_idx));
LOG("%d entries", n_entries);
for (int i = 1; i <= n_entries; ++i)
{
// Push inner table onto stack.
lua_rawgeti(L, entries_table_idx, i);
int item_table_idx = 1;
luaL_checktype(L, -1, LUA_TTABLE);
int n_items = static_cast<int>(lua_rawlen(L, -1));
LOG("%d items", n_items);
for (int i = 1; i <= n_items; ++i)
{
// Push value from table onto stack.
lua_rawgeti(L, -1, i);
int is_number = 0;
// Read value
int x = static_cast<int>(lua_tonumberx(L, -1, &is_number));
if (!is_number)
{
// fire an error
luaL_checktype(L, -1, LUA_TNUMBER);
}
LOG("Got: %d", x);
// pop value off stack
lua_pop(L, 1);
}
// pop table off stack
lua_pop(L, 1);
}
}
LOG("Overwrite the values");
{
int entries_table_idx = 1;
luaL_checktype(L, entries_table_idx, LUA_TTABLE);
int n_entries = static_cast<int>(lua_rawlen(L, entries_table_idx));
LOG("%d entries", n_entries);
for (int i = 1; i <= n_entries; ++i)
{
// Push inner table onto stack.
lua_rawgeti(L, entries_table_idx, i);
int item_table_idx = 1;
luaL_checktype(L, -1, LUA_TTABLE);
int n_items = static_cast<int>(lua_rawlen(L, -1));
LOG("%d items", n_items);
for (int j = 1; j <= n_items; ++j)
{
int x = j + 10;
// Push new value onto stack.
lua_pushinteger(L, x);
// rawseti pops the value off. Need to go -2 to get to the
// table because the value is on top.
lua_rawseti(L, -2, j);
LOG("Wrote: %d", x);
}
// pop table off stack
lua_pop(L, 1);
}
}
// No return values
return 0;
}
输出:
BEFORE = { { 44, 34, 0, 7 }, { 4, 4, 1, 3 } }
Read the values and print them out to show that it's working.
2 entries
4 items
Got: 44
Got: 34
Got: 0
Got: 7
4 items
Got: 4
Got: 4
Got: 1
Got: 3
Overwrite the values
2 entries
4 items
Wrote: 11
Wrote: 12
Wrote: 13
Wrote: 14
4 items
Wrote: 11
Wrote: 12
Wrote: 13
Wrote: 14
AFTER = { { 11, 12, 13, 14 }, { 11, 12, 13, 14 } }