I recently found myself doing a lot of this sort of thing.
bool lua_t::load(const std::string& filename)
{
lua_pushcfunction(state_, traceback_function);
if (luaL_loadfile(state_, filename.c_str()) != 0)
{
lua_pop(state_, 1);
return false;
}
if (lua_pcall(state_, 0, LUA_MULTRET, -2) != 0)
{
lua_pop(state_, 1);
return false;
}
lua_pop(state_, 1);
return true;
}
The “sort of thing” I’m referring to is restoring the state of the Lua stack at every exit point from a function which manipulates it. In the above case, I had to use three distinct calls to lua_pop to achieve this. Today, I found a new approach that can simplify dealing with the Lua stack from C++.
struct stack_bookmark_t
{
explicit stack_bookmark_t(lua_State& state_)
:
state_(&state),
top_(lua_gettop(state_))
{
}
~stack_bookmark_t()
{
lua_settop(state_, top_);
}
private:
lua_State* state_;
int top_;
};
The motivating example changes to this.
bool lua_t::load(const std::string& filename)
{
stack_bookmark_t bookmark(*state_);
lua_pushcfunction(state_, traceback_function);
if (luaL_loadfile(state_, filename.c_str()) != 0)
{
return false;
}
if (lua_pcall(state_, 0, LUA_MULTRET, -2) != 0)
{
return false;
}
return true;
}
At every exit from this function scope, the destructor of stack_bookmark_t ensures that the stack height is restored to its prior state.