Я новичок во внедрении 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)
Задача ещё не решена.