summaryrefslogtreecommitdiffstats
path: root/src/Bindings/LuaState.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Bindings/LuaState.cpp')
-rw-r--r--src/Bindings/LuaState.cpp105
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;
}