理解 Lua 與 C/C++ 交互的第一步,是徹底掌握虛擬堆棧機制。這是 Lua 設計的核心:Lua 與宿主語言不直接共享內存對象,而是通過一個「無處不在」的虛擬堆棧作為唯一通信介質。本文深度解析堆棧索引模型、內存佈局、數據類型統一表示、以及垃圾回收交互邊界。
TValue stack[max_stack_len],在 lua_State 創建時分配(見 lstate.c stack_init)
1, 2, 3... top-1, -2, -3... -top正索引 = 負索引 + top + 1Lua 實現動態類型的關鍵:值與類型標籤綁定。

// 簡化版 TValue 結構
typedef struct TValue {
Value value; // 聯合體:存儲實際數據
int tt; // 類型標籤:LUA_TNIL, LUA_TBOOLEAN, LUA_TNUMBER...
} TValue;
typedef union Value {
void* p; // light userdata
lua_Number n; // 數值(double/float)
int b; // 布爾值(0/1)
GCObject* gc; // 所有需 GC 管理的對象:string, table, closure, userdata, thread, proto, upvalue
} Value;
| Lua 類型 | C 對應 | 存儲位置 | GC 管理 |
|---|---|---|---|
| nil | — | 棧上直接存儲(tt = LUA_TNIL) | 無 |
| boolean | int (0/1) | 棧上直接存儲(value.b) | 無 |
| number | lua_Number | 棧上直接存儲(value.n) | 無 |
| light userdata | void* | 棧上直接存儲(value.p) | 無(裸指針) |
| string | TString* | 棧存指針(value.gc) | 是 |
| table | Table* | 棧存指針(value.gc) | 是 |
| function (closure) | Closure* | 棧存指針(value.gc) | 是 |
| userdata | Udata* | 棧存指針(value.gc) | 是 |
| thread | lua_State* | 棧存指針(value.gc) | 是 |
核心結論:
所有 lua_push* 族函數均具備「創建 Lua 值並壓入棧頂」語義:
lua_pushnumber(L, 5):修改棧頂槽,tt = LUA_TNUMBER, value.n = 5lua_pushstring(L, "str"):Lua 內部創建 TString 對象(含內容拷貝/驻留),棧頂綁定其指針lua_pushcclosure(L, func, 0):創建 Closure 對象封裝 C 函數指針lua_createtable(L, 0, 0):創建 Table 對象關鍵點:一旦壓入,該值進入 Lua 世界,生命周期完全由 Lua 管理,C 端不再持有所有權。
lua_to* 族函數僅支持有 C 對應類型的值:
lua_tonumber / lua_tointeger / lua_toboolean / lua_tostring / lua_topointerlua_totable、lua_toclosure 等——引用類型無法直接「取出」,只能通過 API 間接操作取出時實際上是從 TValue 讀取並轉換為 C 原生類型,不影響堆上對象。
執行以下代碼可復現文檔中的棧示意圖:
lua_State* L = luaL_newstate();
// 1. 壓入閉包
lua_pushcclosure(L, my_c_func, 0); // stack[1] = closure
// 2. 壓入表
lua_createtable(L, 0, 0); // stack[2] = table
// 3. 壓入數值
lua_pushnumber(L, 343); // stack[3] = number
// 4. 壓入字符串
lua_pushstring(L, "mystr"); // stack[4] = string
// 當前棧頂索引 = 4,棧底 = 1
// 結構完全對應文檔圖示:closure, table, number, string

lua_pop/lua_settop 彈出值時,僅移除棧槽引用,不直接銷毀堆對象(由 GC 掃描決定)虛擬堆棧是 Lua 與 C/C++ 交互的契約介面:
TValue = {值, 類型標籤} 實現動態類型徹底理解上述機制,是編寫正確、高效、無內存泄漏的 Lua-C++ 綁定代碼的前提。下一篇將詳細講解具體堆棧操作 API 族與實戰模式。