![](/img/trans.png)
[英]How to create a multi-dimensional Lua table with Lua C Api...?
[英]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.