繁体   English   中英

如何使用C-API在Lua 5.1中的表中创建表?

[英]How to create table in table in Lua 5.1 using C-API?

我需要在Lua 5.1 C-API中创建这样的构造,而不是在Lua 5.2及更高版本中

a = {["b"] = {["c"] = {["d"] = {["e"] = "GOOD"}}}}

print(a.b.c.d.e);

预期结果:良好

感谢您的回答!

Lua C API是基于堆栈的。 这意味着大多数C API函数的行为不仅取决于给定的参数,还取决于Lua堆栈的内容(它是lua_State*变量的一部分,通常称为L )。 就堆栈内容以及它如何影响堆栈元素而言,特定的API函数会有什么期望,您必须在Lua手册中进行查找。

让我们从创建表开始并将其分配给全局变量a

lua_newtable( L );
lua_setglobal( L, "a" );

这等效于Lua代码段: a = {}

lua_newtable()的文档告诉我们,该函数将新表推入Lua堆栈的顶部。 这非常适合lua_setglobal() ,它从堆栈顶部弹出一个值,并将其分配给给定名称的全局变量。 因此,两个功能组合在一起(如上面的代码段所示)在堆栈效果方面是平衡的 关于堆栈平衡的代码段的好处是,您可以将它们插入任何位置,并且组合的代码仍然有效。 (一般规则是: 只要(合并的)堆栈效果相同,就可以用一系列语句替换单个语句,反之亦然 。)例如:

lua_newtable( L );  /* ==> stack: ..., {} */
lua_pushnil( L ); /* ==> stack: ..., {}, nil */
lua_pop( L, 1 ); /* ==> stack: ..., {} */
lua_setglobal( L, "a" ); /* ==> stack: ... */

仍将表分配给全局变量a因为lua_pushnil( L ); lua_pop( L, 1 ); 合并不要更改Lua堆栈的内容。 代替这种无用的推入/弹出操作,我们将添加代码,以将表压入堆栈之后 ,将其从堆栈中删除并分配给全局变量之前对其进行修改。 就像我说的那样,您可以在两个Lua C API函数之间的任意位置插入堆栈平衡的代码段,因此您只需确定堆栈包含所有需要的元素的正确位置即可。

我们要向表中添加键"b"和另一个表作为值的字段。 Lua C API函数就是lua_settable() (还有其他一些仅对某些键类型有效的便捷函数,例如lua_setfield() ,但这里我们将使用lua_settable() )。 lua_settable()需要该表将键/值对存储在Lua堆栈上的某个位置 (这通常意味着您必须将堆栈索引作为参数传递),并且键和值作为两个top-堆栈上的大多数元素。 lua_settable()会同时弹出键和值(但不是表lua_settable()

lua_newtable( L );  /* ==> stack: ..., {} */
lua_pushliteral( L, "b" ); /* ==> stack: ..., {}, "b" */
lua_newtable( L ); /* ==> stack: ..., {}, "b", {} */
lua_settable( L, -3 ); /* ==> stack: ..., {} */
lua_setglobal( L, "a" ); /* ==> stack: ... */

等效的Lua代码为a = { b = {} }

通常,您实际上并不真正在意Lua堆栈某个点以下的内容,而这正是相对于堆栈顶部的索引(上面的代码片段中的-3 )起作用的地方。 -3指的是紧靠键"b" (位于-2 )下方和另一个表(位于-1的堆栈顶部)下方的表。

您可能已经看到了要进行的操作:现在,我们要修改新表,因此我们在正确的位置添加了栈平衡代码(在将新表推入堆栈之后)。 我将跳过一些步骤,并通过缩进指示在哪里插入了代码:

lua_newtable( L );  /* ==> stack: ..., {} */
{
  lua_pushliteral( L, "b" ); /* ==> stack: ..., {}, "b" */
  lua_newtable( L ); /* ==> stack: ..., {}, "b", {} */
  {
    lua_pushliteral( L, "c" ); /* == stack: ..., {}, "b", {}, "c" */
    lua_newtable( L ); /* ==> stack: ..., {}, "b", {}, "c", {} */
    {
      lua_pushliteral( L, "d" );
      lua_newtable( L );
      {
        lua_pushliteral( L, "e" );
        lua_pushliteral( L, "GOOD" );
        lua_settable( L, -3 );
      }
      lua_settable( L, -3 );
    }
    lua_settable( L, -3 ); */ ==> stack: ..., {}, "b", {} */
  }
  lua_settable( L, -3 ); /* ==> stack: ..., {} */
}
lua_setglobal( L, "a" ); /* ==> stack: ... */

使用复杂的堆栈操作开发代码时,通常有助于在关键点打印当前堆栈的内容,或者至少检查堆栈中的元素数量(请参见lua_gettop() )是否符合您的期望。 就是我用的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM