2

我是嵌入 Lua 的新手,并且已经成功地在我的旅程中取得了进展。我将结果存储luaL_loadfile到全局中,以便可以重复调用它。我当前的问题是,当我尝试在当前脚本状态以外的状态下运行脚本内部的脚本时,我得到了段错误。

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;
};

以下是脚本的加载方式:

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;
}

我的执行功能:

 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);
}

我的绑定调用 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);
}

还有我的测试脚本:

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)
4

0 回答 0