2

私は Lua を埋め込むのが初めてで、ここまでの道のりを歩むことができました。結果をグローバルに保存して、luaL_loadfile繰り返し呼び出すことができるようにします。私の現在の問題は、現在のスクリプトの状態以外の状態でスクリプト内でスクリプトを実行しようとすると、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;
};

スクリプトのロード方法は次のとおりです。

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