Archive for July, 2010

Using RAII to simplify using the Lua stack when writing C++ code
2010.07.26

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.