簡體   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