将参数作为参考从 Lua 传递到 C++

纸鸟大师

我注册了一个 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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章