Lua中一個(gè)lua_State就對(duì)應(yīng)一個(gè)lua stack,通常情況下一個(gè)lua stack就足夠了,由此便產(chǎn)生了與C/C++不同的地方:在C/C++中每個(gè)函數(shù)調(diào)用都會(huì)有自己對(duì)應(yīng)的stack,在函數(shù)調(diào)用完成之后,便將其釋放掉,因而不需要擔(dān)心stack會(huì)無(wú)限制地生長(zhǎng)下去;而在C/C++中使用Lua,由于所有的操作都基于同一個(gè)stack,因此需要程序員自己在代碼中做stack的清理工作。
Lua提供了一對(duì)API來(lái)幫助程序員操縱stack:lua_gettop和lua_settop。下面給出兩種清理?xiàng)5姆椒ǎ?br> 1)為每個(gè)操作Lua棧的C/C++函數(shù)添加一個(gè)棧頂位置參數(shù)。在調(diào)用該函數(shù)時(shí)將lua_gettop的結(jié)果作為參數(shù)傳遞,在函數(shù)調(diào)用結(jié)束時(shí)使用lua_settop以傳入的棧頂位置作為參數(shù)恢復(fù)調(diào)用前的棧頂位置。CEGUI中的script module便采用此方法,下面摘錄相關(guān)代碼:

/**//*************************************************************************
Execute script code string
*************************************************************************/
void LuaScriptModule::executeString(const String& str)


{
int top = lua_gettop(d_state);

executeString_impl(str, initErrorHandlerFunc(), top);
cleanupErrorHandlerFunc();
}

void LuaScriptModule::executeString_impl(const String& str, const int err_idx,
const int top)


{
// load code into lua and call it
int error = luaL_loadbuffer(d_state, str.c_str(), str.length(), str.c_str()) ||
lua_pcall(d_state, 0, 0, err_idx);

// handle errors
if (error)

{
String errMsg = lua_tostring(d_state,-1);
lua_settop(d_state,top);
throw ScriptException("Unable to execute Lua script string: '" +
str + "'\n\n" + errMsg + "\n");
}

lua_settop(d_state,top);
}
2)利用局部變量的創(chuàng)建與銷毀來(lái)自動(dòng)實(shí)現(xiàn)stack清理。下面為局部變量的類型
struct LuaStackAutoPopup

{
lua_State* mBackupLS;;
int mPos;
LuaStackAutoPopup( lua_State* vpSL )

{
mPos = lua_gettop( vpSL );
mBackupLS = vpSL;
}

void Popup( )

{
lua_settop( mBackupLS,mPos );
mBackupLS = NULL;
}

~LuaStackAutoPopup( )

{
if( mBackupLS )
lua_settop( mBackupLS,mPos );
}
};
利用此機(jī)制,改造方法1中的executeString:

/**//*************************************************************************
Execute script code string
*************************************************************************/
void LuaScriptModule::executeString(const String& str)


{
LuaStackAutoPopup stack(d_state);

executeString_impl(str, initErrorHandlerFunc());
cleanupErrorHandlerFunc();
}

void LuaScriptModule::executeString_impl(const String& str, const int err_idx)


{
// load code into lua and call it
int error = luaL_loadbuffer(d_state, str.c_str(), str.length(), str.c_str()) ||
lua_pcall(d_state, 0, 0, err_idx);

// handle errors
if (error)

{
String errMsg = lua_tostring(d_state,-1);
throw ScriptException("Unable to execute Lua script string: '" +
str + "'\n\n" + errMsg + "\n");
}
}