Heath's Blog

There is no end, it is just the beginning! - A Game Developer's Notes

C/C++中Lua栈的清理

    Lua中一个lua_State就对应一个lua stack,通常情况下一个lua stack就足够了,由此便产生了与C/C++不同的地方:在C/C++中每个函数调用都会有自己对应的stack,在函数调用完成之后,便将其释放掉,因而不需要担心stack会无限制地生长下去;而在C/C++中使用Lua,由于所有的操作都基于同一个stack,因此需要程序员自己在代码中做stack的清理工作。
    Lua提供了一对API来帮助程序员操纵stack:lua_gettop和lua_settop。下面给出两种清理栈的方法:
    1)为每个操作Lua栈的C/C++函数添加一个栈顶位置参数。在调用该函数时将lua_gettop的结果作为参数传递,在函数调用结束时使用lua_settop以传入的栈顶位置作为参数恢复调用前的栈顶位置。CEGUI中的script module便采用此方法,下面摘录相关代码:
/*************************************************************************
    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, 
00, 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)利用局部变量的创建与销毁来自动实现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 );
        }

    }
;
    利用此机制,改造方法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, 
00, 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");
    }

}

posted on 2009-04-25 15:24 Heath 阅读(4883) 评论(1)  编辑 收藏 引用 所属分类: Script Programming

Feedback

# re: C/C++中Lua栈的清理[未登录] 2011-12-24 18:52 patz

对称操作使用RAII来清理的确是一个best practice.  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理