2

I'm new to embedding Lua and have managed to get this far along my journey. I store the result of luaL_loadfile into a global so it can be called repeatedly. My current issue at hand is that when I attempt to run a script inside of a script on a state other than the current scripts state I get a segfault.

struct State
{
    // deleted and defaulted ctors removed for brevity
    State(std::string name, uint32_t id) : 
        id(id), state(luaL_newstate()), name(std::move(name))
    {
        assert(this->state != nullptr && "state is nullptr");
        assert(this->name != "" && "Name is empty");

        luaL_openlibs(state);
        lua_settop(state, 0);
    }

    ~State()
    {
        lua_close(state);
    }

    uint32_t id;
    lua_State* state;
    std::string name;
};

struct Script
{
    // deleted and defaulted ctors removed for brevity
    Script(std::string name, uint32_t id, uint32_t stateId) :
        id(id), stateId(stateId), name(name) { }

    uint32_t id;
    uint32_t stateId;
    std::string name;
};

Here is how scripts are loaded:

bool ScriptEngine::LoadScript(State& state, std::string filename)
{
    auto success(luaL_loadfile(state.state, filename.c_str()) == 0);
    lua_setglobal(state.state, filename.c_str());

    scripts.emplace_back(filename, nextScriptId, state.id);
    ++nextScriptId;

    return success;
}

My execution function:

 int ScriptEngine::RunScript(Script& script)
 {
    auto state(GetState(script.stateId));
    assert(state != nullptr && "Script state is invalid");

    lua_getglobal(state->state, script.name.c_str());
    // Segfaults in the above line in index2adr called by lua_getfield 
    // if the state is not the same as the current state

    auto top(lua_gettop(state->state));
    if(lua_pcall(state->state, 0, LUA_MULTRET, 0))
    {
        std::cout << "unable to run script " << script.name << " " << 
            lua_tostring(state->state, -1) << std::endl;
        assert(0);
    }

    return top - lua_gettop(state->state);
}

My binding which calls ScriptEngine::RunScript(Script&)

int RunScript(lua_State* state)
{
    auto script((Script*)lua_touserdata(state, -1));

    lua_pushliteral(state, "ScriptEngine"); 
    lua_gettable(state, LUA_REGISTRYINDEX);

    auto engine((ScriptEngine*)lua_touserdata(state, -1));

    return engine->RunScript(*script);
}

And my test script:

local script = ScriptEngine.GetScript("config.txt")
print(script)

local rets = ScriptEngine.RunScript(script)
-- crash happens in the above line if the target script has a 
-- separate state than this script itself

print(rets)
hjpotter92
  • 78,589
  • 36
  • 144
  • 183
bsdunx
  • 137
  • 7

0 Answers0