我注册了一个 Lua 函数,它需要一个元表作为参数,我想在 C++ 运行时修改表的内容:
int operate(lua_State *L)
{
std::vector<int> values{};
if (auto length = get_length_at_index(L, 1))
{
result.reserve(length);
lua_pushnil(L);
while (lua_next(L, 1))
{
result.push_back(lua_tointeger(L, -1));
lua_pop(L, 1);
}
}
for (auto &v : values)
{
v *= 2;
}
return 0;
}
int main()
{
auto L = luaL_newstate();
luaL_dofile(L, "script.lua");
lua_register(L, "operate", operate);
return 0;
}
上面的代码"lua.script"
看起来像这样:
values = {1, 2, 3, 4, 5, 6}
operate(values)
for index = 1, #values do
print(values[index])
end
预期输出是 1 到 6 乘以 2 的值,但输出是未修改的值。很明显,发生这种情况是因为我正在将元表复制到 astd::vector
并修改副本。
有没有办法从 C++ 运行时对 Lua 对象进行操作,以反映从 C++ 应用的更改?
PS:我知道我可以将表作为函数返回值返回,但我想知道是否还有其他选项。
编辑:我没有看到你已经知道为什么。为将来的读者,解释已移至底部。
在第一个循环之后,您的表仍然位于堆栈顶部,简化了以下解决方案。将您的第二个循环替换为:
int count = int(result.size());
for (int i = 0; i < count; ++i) {
lua_pushinteger(L, result[i] * 2);
lua_rawseti(L, -2, i);
}
-2 指栈顶以下的 lua 值(同理,-1 指栈顶)。当rawseti
到达您的LUA堆栈看起来是这样的:
[-1]:result[i]
[-2] 的副本:您的values
表
rawseti
从堆栈顶部弹出值并将其存储在指定的表和索引中,使该表再次成为堆栈顶部。
请注意,您实际上可以在第一个循环中执行此操作,但是您应该避免养成这种习惯,因为某些 lua 操作在迭代时会导致未定义的行为,并且这会进一步使代码复杂化。请参阅此帖子以进行澄清。
为什么会发生这种情况?
总之,代码写入 C++ 内存,而不是 lua 表。
第一个循环进行迭代,读取每个值并将其添加到result
容器中。
lua_pushnil(L);
while (lua_next(L, 1))
{
result.push_back(lua_tointeger(L, -1));
lua_pop(L, 1);
}
第二个循环将C++容器中每个元素的值加倍。
for (auto &v : values)
{
v *= 2;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句