【问题标题】:Moving a lua table in C api在 C api 中移动 lua 表
【发布时间】:2013-06-17 19:39:30
【问题描述】:

我正在尝试使用 lua C api 将一个表移动到另一个表。例如,我有一个具有这种结构的表:

a[b][c][d][e] = value

我想将表 d 移动到 a[b] 下,我可以在 Lua 中完成,如下所示:

a[b][d] = a[b][c][d]
a[b][c][d] = nil

我目前的做法是在堆栈上加载 a[b][c][d] 表,所以堆栈看起来像:

Index  Value
-1     d table
-2     c table
-3     b table
-4     a table

然后将 a[b] 加载到堆栈中,如下所示:

Index  Value
-1     b table
-2     a table
-3     d table
-4     c table
-5     b table
-6     a table

然后将d的key放入栈中,将d的key和table b插入到table d下面,所以栈为:

Index  Value
-1     d table
-2     d key
-3     b table
-4     a table
-5     c table
-6     b table
-7     a table

然后我使用 lua_settable(L, -3), 来做 b[d] = d。

这种方法适用于非表键,但不适用于表键。所以它会失败,比如:

a[b][c][{}][d] = value
a[b] = a[b][c][{}][d]

注意,我知道上面给出的 lua 会失败,因为键是一个新的 lua 表,我只是想说明一下。

我也尝试过从表中删除父项(这样做 a[b] = b, lua_setglobal(L, a))也没有任何运气。有谁知道我哪里出错了?

编辑: 关于如何将键/值推入堆栈的小代码 sn-p。这里的目标是将一个表从一个表结构移动到另一个表结构(或者正如我在代码中所说的,重新定义它)

http://pastebin.com/Y4540Wss

解决方案:

问题是表有一些元表函数,它阻止了对表的更改(本质上,编写脚本的人有一个结构很重要的配置表,因此导致了这个问题。)

【问题讨论】:

    标签: c++ lua lua-table lua-api


    【解决方案1】:

    如果我正确理解你的描述,这个 Lua 代码可以满足你的要求:

    local ab = a[b]
    ab[d], ab[c][d] = ab[c][d], nil
    

    至于在 Lua C API 中实现,lua2c 对机器翻译很有帮助:

    enum { lc_nformalargs = 0 };
    const int lc_nactualargs = lua_gettop(L);
    const int lc_nextra = (lc_nactualargs - lc_nformalargs);
    
    /* local ab = a[b] */
    lua_getfield(L,LUA_ENVIRONINDEX,"a");
    lua_getfield(L,LUA_ENVIRONINDEX,"b");
    lua_gettable(L,-2);
    lua_remove(L,-2);
    assert(lua_gettop(L) - lc_nextra == 1);
    
    /* ab[d], ab[c][d] = ab[c][d], nil */
    lua_getfield(L,LUA_ENVIRONINDEX,"c");
    lua_gettable(L,(1 + lc_nextra));
    lua_getfield(L,LUA_ENVIRONINDEX,"d");
    lua_gettable(L,-2);
    lua_remove(L,-2);
    lua_pushnil(L);
    lua_getfield(L,LUA_ENVIRONINDEX,"c");
    lua_gettable(L,(1 + lc_nextra));
    lua_insert(L,-2);
    lua_getfield(L,LUA_ENVIRONINDEX,"d");
    lua_insert(L,-2);
    lua_settable(L,-3);
    lua_pop(L,1);
    lua_getfield(L,LUA_ENVIRONINDEX,"d");
    lua_insert(L,-2);
    lua_settable(L,(1 + lc_nextra));
    assert(lua_gettop(L) - lc_nextra == 1);
    return 0;
    

    我还没有开发出一种可读的方式来编写堆栈操作。

    【讨论】:

    • 使用lua_getglobal 而不是lua_getfield
    • @lhf 好的,谢谢。我看到 LUA_ENVIRONINDEX 自 Lua 5.2 起已被删除。
    • 还是不行。可能有所不同,但其中一个表的键实际上是另一个表。当我没有带表键的表时,一切正常。我不确定如何在 lua2c 中概括这一点,因为该表可能没有像 f = {}; 这样的引用。 a[f] = {}。就像 a[{}] = {} 完成的,所以我必须使用 luaL_ref 来获取堆栈上的 table 的 key。
    猜你喜欢
    • 2011-05-30
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 2011-03-20
    • 2012-03-13
    • 2013-10-03
    • 2016-08-04
    相关资源
    最近更新 更多