diff options
Diffstat (limited to 'src/Bindings/LuaState.cpp')
-rw-r--r-- | src/Bindings/LuaState.cpp | 105 |
1 files changed, 89 insertions, 16 deletions
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index ac5ce47e1..c6be7be3c 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -735,17 +735,20 @@ bool cLuaState::CallFunction(int a_NumResults) ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1)); // The function to call ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 2)); // The error handler - int s = lua_pcall(m_LuaState, m_NumCurrentFunctionArgs, a_NumResults, -m_NumCurrentFunctionArgs - 2); + // Save the current "stack" state and reset, in case the callback calls another function: + AString CurrentFunctionName; + std::swap(m_CurrentFunctionName, CurrentFunctionName); + int NumArgs = m_NumCurrentFunctionArgs; + m_NumCurrentFunctionArgs = -1; + + // Call the function: + int s = lua_pcall(m_LuaState, NumArgs, a_NumResults, -NumArgs - 2); if (s != 0) { // The error has already been printed together with the stacktrace - LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), m_CurrentFunctionName.c_str()); - m_NumCurrentFunctionArgs = -1; - m_CurrentFunctionName.clear(); + LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), CurrentFunctionName.c_str()); return false; } - m_NumCurrentFunctionArgs = -1; - m_CurrentFunctionName.clear(); // Remove the error handler from the stack: lua_remove(m_LuaState, -a_NumResults - 1); @@ -941,10 +944,42 @@ bool cLuaState::CheckParamFunction(int a_StartParam, int a_EndParam) lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); - AString ErrMsg = Printf("Error in function '%s' parameter #%d. Function expected, got %s", + luaL_error(m_LuaState, "Error in function '%s' parameter #%d. Function expected, got %s", + (entry.name != NULL) ? entry.name : "?", i, GetTypeText(i).c_str() + ); + return false; + } // for i - Param + + // All params checked ok + return true; +} + + + + + +bool cLuaState::CheckParamFunctionOrNil(int a_StartParam, int a_EndParam) +{ + ASSERT(IsValid()); + + if (a_EndParam < 0) + { + a_EndParam = a_StartParam; + } + + for (int i = a_StartParam; i <= a_EndParam; i++) + { + if (lua_isfunction(m_LuaState, i) || lua_isnil(m_LuaState, i)) + { + continue; + } + // Not the correct parameter + lua_Debug entry; + VERIFY(lua_getstack(m_LuaState, 0, &entry)); + VERIFY(lua_getinfo (m_LuaState, "n", &entry)); + luaL_error(m_LuaState, "Error in function '%s' parameter #%d. Function expected, got %s", (entry.name != NULL) ? entry.name : "?", i, GetTypeText(i).c_str() ); - LogStackTrace(); return false; } // for i - Param @@ -1206,7 +1241,7 @@ void cLuaState::LogStack(const char * a_Header) void cLuaState::LogStack(lua_State * a_LuaState, const char * a_Header) { LOGD((a_Header != NULL) ? a_Header : "Lua C API Stack contents:"); - for (int i = lua_gettop(a_LuaState); i >= 0; i--) + for (int i = lua_gettop(a_LuaState); i > 0; i--) { AString Value; int Type = lua_type(a_LuaState, i); @@ -1240,13 +1275,21 @@ int cLuaState::ReportFnCallErrors(lua_State * a_LuaState) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cLuaState::cRef: +cLuaState::cRef::cRef(void) : + m_LuaState(NULL), + m_Ref(LUA_REFNIL) +{ +} + + + + + cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) : - m_LuaState(a_LuaState) + m_LuaState(NULL), + m_Ref(LUA_REFNIL) { - ASSERT(m_LuaState.IsValid()); - - lua_pushvalue(m_LuaState, a_StackPos); // Push a copy of the value at a_StackPos onto the stack - m_Ref = luaL_ref(m_LuaState, LUA_REGISTRYINDEX); + RefStack(a_LuaState, a_StackPos); } @@ -1255,12 +1298,42 @@ cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) : cLuaState::cRef::~cRef() { - ASSERT(m_LuaState.IsValid()); + if (m_LuaState != NULL) + { + UnRef(); + } +} + + + + + +void cLuaState::cRef::RefStack(cLuaState & a_LuaState, int a_StackPos) +{ + ASSERT(a_LuaState.IsValid()); + if (m_LuaState != NULL) + { + UnRef(); + } + m_LuaState = &a_LuaState; + lua_pushvalue(a_LuaState, a_StackPos); // Push a copy of the value at a_StackPos onto the stack + m_Ref = luaL_ref(a_LuaState, LUA_REGISTRYINDEX); +} + + + + + +void cLuaState::cRef::UnRef(void) +{ + ASSERT(m_LuaState->IsValid()); // The reference should be destroyed before destroying the LuaState if (IsValid()) { - luaL_unref(m_LuaState, LUA_REGISTRYINDEX, m_Ref); + luaL_unref(*m_LuaState, LUA_REGISTRYINDEX, m_Ref); } + m_LuaState = NULL; + m_Ref = LUA_REFNIL; } |