#include "lua_state.h" #include #include "sgp_logger.h" #include LuaState::LuaState(lua_State* state, bool own) : _L(state), _own(own), _registry(state) { } LuaState::LuaState() : _L(NULL), _own(true), _registry(NULL) { //_L = lua_open(); //_registry._L = _L; } LuaState::~LuaState() { } void LuaState::init(bool init_libs) { if(!_L) { _L = lua_open(); if(init_libs) { luaL_openlibs(_L); } _registry._L = _L; } } void LuaState::close() { if(_L && _own) { lua_close(_L); } } #include bool LuaState::EvalFile(const char* filename) { try { vfs::COpenReadFile rfile(filename); vfs::UInt32 size = rfile.file().getSize(); std::vector buffer(size+1); rfile.file().read(&buffer[0], size); buffer[size] = 0; return this->EvalString((char*)&buffer[0], size, filename); } catch(std::exception &ex) { SGP_ERROR(ex.what()); } return false; } bool LuaState::CallFunction(const char* function_name) { if(function_name) { // call function lua_getglobal(_L, function_name); if(lua_isfunction(_L, -1)) { if( lua_pcall(_L, 0, 1, 0) != 0 ) { std::string err = lua_tostring(_L, -1); std::wstringstream wss; wss << L"Execution of lua function '" << vfs::String::as_utf16(function_name) << L"' failed : "; wss << vfs::String::as_utf16(err); SGP_THROW(wss.str().c_str()); } return true; } } return false; } bool LuaState::EvalString(const wchar_t *lua_str, size_t length, const char* id_str) { std::string s = vfs::String::as_utf8(lua_str, length); return this->EvalString(s.c_str(), s.length(), id_str); } bool LuaState::EvalString(const char *lua_str, size_t length, const char* id_str) { int error; if(length == 0) { length = strlen(lua_str); } error = luaL_loadbuffer(_L, lua_str, length, id_str) || lua_pcall(_L, 0, 0, 0); if (error) { const char *error = lua_tostring(_L, -1); int len = strlen( error); if (len >= 7 && !strcmp( error + len - 7, "''")) { lua_pop(_L, 1); /* pop error message from the stack */ return false; } std::string s = lua_tostring(_L, -1); SGP_THROW(s); //printf( "%s\n", lua_tostring(L, -1)); //lua_pop(L, 1); /* pop error message from the stack */ //return true; } return true; } ///////////////////////////////////////////////////////////////////////// LuaState::Registry::Registry(lua_State* L) : _L(L) { } void LuaState::Registry::CreateCallbackTable() { lua_getfield(_L, LUA_REGISTRYINDEX, "__CallBackRegistry"); if(lua_isnil(_L,-1)) { lua_pop(_L,1); // pop 'nil' from stack lua_newtable(_L); lua_setfield(_L,LUA_REGISTRYINDEX,"__CallBackRegistry"); // 'setfield' removes value from stack return; } else if(lua_istable(_L,-1)) { lua_pop(_L,1); return; } SGP_THROW(L"Could not create callback registy table"); } void LuaState::Registry::GetCallbackTable() { lua_getfield(_L, LUA_REGISTRYINDEX, "__CallBackRegistry"); if(!lua_istable(_L,-1)) { SGP_THROW("CallBack registry table does not exist"); } } void LuaState::Registry::SetCallback(const char* callback_name) { // function is at (L, -2) // user data value is at (L, -1) this->GetCallbackTable(); lua_pushvalue(_L, -2); lua_rawget(_L, -2); if(!lua_istable(_L, -1)) { lua_pop(_L, 1); // remove 'nil' // set new table lua_pushvalue(_L, -2); lua_newtable(_L); lua_rawset(_L, -3); // get table lua_pushvalue(_L, -2); lua_rawget(_L, -2); } if(!lua_istable(_L,-1)) { SGP_THROW("Could not create callback"); } lua_pushvalue(_L, -4); lua_setfield(_L, -2, callback_name); lua_pop(_L, 4); } void LuaState::Registry::GetCallback(const char* callback_name) { // user data is at (L, -1) this->GetCallbackTable(); lua_pushvalue(_L, -2); lua_rawget(_L, -2); if(lua_istable(_L, -1)) { lua_getfield(_L, -1, callback_name); if(lua_isfunction(_L, -1)) { lua_insert(_L, -4); lua_pop(_L, 3); if(!lua_isfunction(_L,-1)) { SGP_THROW("messed up stack"); } return; } // no callback defined lua_pop(_L, 4); } // no table created lua_pop(_L, 3); // also pops user data return; } void LuaState::Registry::CreateUserDataTable() { lua_getfield(_L, LUA_REGISTRYINDEX, "__UserData"); if(lua_isnil(_L,-1)) { lua_pop(_L,1); // pop 'nil' from stack lua_newtable(_L); lua_setfield(_L,LUA_REGISTRYINDEX,"__UserData"); // 'setfield' removes value from stack return; } else if(lua_istable(_L,-1)) { lua_pop(_L,1); return; } SGP_THROW(L"Could not create User Data registy table"); } void LuaState::Registry::GetUserDataTable() { lua_getfield(_L, LUA_REGISTRYINDEX, "__UserData"); if(!lua_istable(_L,-1)) { SGP_THROW("User Data registry table does not exist"); } } /************************************************************************************/ #include class LuaStateManager { public: ~LuaStateManager() { _states.clear(); }; static LuaStateManager& instance() { static LuaStateManager lsm; return lsm; }; LuaState& GetState(lua::State eState) { return _states[eState]; } private: LuaStateManager() {}; static std::map _states; }; std::map LuaStateManager::_states; void LuaState::INIT(lua::State state_id, bool init_libs) { LuaStateManager::instance().GetState(state_id).init(init_libs); } LuaState LuaState::INIT(bool init_libs) { LuaState L; L.init(init_libs); return L; } void LuaState::CLOSE(lua::State state_id) { LuaStateManager::instance().GetState(state_id).close(); } void LuaState::CLOSE(LuaState state) { state.close(); } LuaState LuaState::GET(lua::State state_id) { return LuaStateManager::instance().GetState(state_id); }