Implemented cPluginManager:CallPlugin() API.
This function supersedes cPlugin:Call(), is safer to use in regards to multithreading and once again removes the need for the cPlugin class being exported at all.
This commit is contained in:
@@ -235,7 +235,7 @@ bool cLuaState::PushFunction(const char * a_FunctionName)
|
||||
if (!lua_isfunction(m_LuaState, -1))
|
||||
{
|
||||
LOGWARNING("Error in %s: Could not find function %s()", m_SubsystemName.c_str(), a_FunctionName);
|
||||
lua_pop(m_LuaState, 1);
|
||||
lua_pop(m_LuaState, 2);
|
||||
return false;
|
||||
}
|
||||
m_CurrentFunctionName.assign(a_FunctionName);
|
||||
@@ -258,7 +258,7 @@ bool cLuaState::PushFunction(int a_FnRef)
|
||||
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // same as lua_getref()
|
||||
if (!lua_isfunction(m_LuaState, -1))
|
||||
{
|
||||
lua_pop(m_LuaState, 1);
|
||||
lua_pop(m_LuaState, 2);
|
||||
return false;
|
||||
}
|
||||
m_CurrentFunctionName = "<callback>";
|
||||
@@ -282,7 +282,7 @@ bool cLuaState::PushFunction(const cTableRef & a_TableRef)
|
||||
if (!lua_istable(m_LuaState, -1))
|
||||
{
|
||||
// Not a table, bail out
|
||||
lua_pop(m_LuaState, 1);
|
||||
lua_pop(m_LuaState, 2);
|
||||
return false;
|
||||
}
|
||||
lua_getfield(m_LuaState, -1, a_TableRef.GetFnName());
|
||||
@@ -742,6 +742,10 @@ bool cLuaState::CallFunction(int a_NumResults)
|
||||
}
|
||||
m_NumCurrentFunctionArgs = -1;
|
||||
m_CurrentFunctionName.clear();
|
||||
|
||||
// Remove the error handler from the stack:
|
||||
lua_remove(m_LuaState, -a_NumResults - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1025,21 +1029,184 @@ void cLuaState::LogStackTrace(lua_State * a_LuaState)
|
||||
|
||||
AString cLuaState::GetTypeText(int a_StackPos)
|
||||
{
|
||||
int Type = lua_type(m_LuaState, a_StackPos);
|
||||
switch (Type)
|
||||
return lua_typename(m_LuaState, lua_type(m_LuaState, a_StackPos));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cLuaState::CallFunctionWithForeignParams(
|
||||
const AString & a_FunctionName,
|
||||
cLuaState & a_SrcLuaState,
|
||||
int a_SrcParamStart,
|
||||
int a_SrcParamEnd
|
||||
)
|
||||
{
|
||||
ASSERT(IsValid());
|
||||
ASSERT(a_SrcLuaState.IsValid());
|
||||
|
||||
// Store the stack position before any changes
|
||||
int OldTop = lua_gettop(m_LuaState);
|
||||
|
||||
// Push the function to call, including the error handler:
|
||||
if (!PushFunction(a_FunctionName.c_str()))
|
||||
{
|
||||
case LUA_TNONE: return "TNONE";
|
||||
case LUA_TNIL: return "TNIL";
|
||||
case LUA_TBOOLEAN: return "TBOOLEAN";
|
||||
case LUA_TLIGHTUSERDATA: return "TLIGHTUSERDATA";
|
||||
case LUA_TNUMBER: return "TNUMBER";
|
||||
case LUA_TSTRING: return "TSTRING";
|
||||
case LUA_TTABLE: return "TTABLE";
|
||||
case LUA_TFUNCTION: return "TFUNCTION";
|
||||
case LUA_TUSERDATA: return "TUSERDATA";
|
||||
case LUA_TTHREAD: return "TTHREAD";
|
||||
LOGWARNING("Function '%s' not found", a_FunctionName.c_str());
|
||||
lua_pop(m_LuaState, 2);
|
||||
return -1;
|
||||
}
|
||||
return Printf("Unknown (%d)", Type);
|
||||
|
||||
// Copy the function parameters to the target state
|
||||
if (CopyStackFrom(a_SrcLuaState, a_SrcParamStart, a_SrcParamEnd) < 0)
|
||||
{
|
||||
// Something went wrong, fix the stack and exit
|
||||
lua_pop(m_LuaState, 2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Call the function, with an error handler:
|
||||
int s = lua_pcall(m_LuaState, a_SrcParamEnd - a_SrcParamStart + 1, LUA_MULTRET, OldTop);
|
||||
if (ReportErrors(s))
|
||||
{
|
||||
LOGWARN("Error while calling function '%s' in '%s'", a_FunctionName.c_str(), m_SubsystemName.c_str());
|
||||
// Fix the stack.
|
||||
// We don't know how many values have been pushed, so just get rid of any that weren't there initially
|
||||
int CurTop = lua_gettop(m_LuaState);
|
||||
if (CurTop > OldTop)
|
||||
{
|
||||
lua_pop(m_LuaState, CurTop - OldTop);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Reset the internal checking mechanisms:
|
||||
m_NumCurrentFunctionArgs = -1;
|
||||
|
||||
// Remove the error handler from the stack:
|
||||
lua_remove(m_LuaState, OldTop + 1);
|
||||
|
||||
// Return the number of return values:
|
||||
return lua_gettop(m_LuaState) - OldTop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cLuaState::CopyStackFrom(cLuaState & a_SrcLuaState, int a_SrcStart, int a_SrcEnd)
|
||||
{
|
||||
/*
|
||||
// DEBUG:
|
||||
LOGD("Copying stack values from %d to %d", a_SrcStart, a_SrcEnd);
|
||||
a_SrcLuaState.LogStack("Src stack before copying:");
|
||||
LogStack("Dst stack before copying:");
|
||||
*/
|
||||
for (int i = a_SrcStart; i <= a_SrcEnd; ++i)
|
||||
{
|
||||
int t = lua_type(a_SrcLuaState, i);
|
||||
switch (t)
|
||||
{
|
||||
case LUA_TNIL:
|
||||
{
|
||||
lua_pushnil(m_LuaState);
|
||||
break;
|
||||
}
|
||||
case LUA_TSTRING:
|
||||
{
|
||||
AString s;
|
||||
a_SrcLuaState.ToString(i, s);
|
||||
Push(s);
|
||||
break;
|
||||
}
|
||||
case LUA_TBOOLEAN:
|
||||
{
|
||||
bool b = (tolua_toboolean(a_SrcLuaState, i, false) != 0);
|
||||
Push(b);
|
||||
break;
|
||||
}
|
||||
case LUA_TNUMBER:
|
||||
{
|
||||
lua_Number d = tolua_tonumber(a_SrcLuaState, i, 0);
|
||||
Push(d);
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA:
|
||||
{
|
||||
// Get the class name:
|
||||
const char * type = NULL;
|
||||
if (lua_getmetatable(a_SrcLuaState, i) == 0)
|
||||
{
|
||||
LOGWARNING("%s: Unknown class in pos %d, cannot copy.", __FUNCTION__, i);
|
||||
lua_pop(m_LuaState, i - a_SrcStart);
|
||||
return -1;
|
||||
}
|
||||
lua_rawget(a_SrcLuaState, LUA_REGISTRYINDEX); // Stack +1
|
||||
type = lua_tostring(a_SrcLuaState, -1);
|
||||
lua_pop(a_SrcLuaState, 1); // Stack -1
|
||||
|
||||
// Copy the value:
|
||||
void * ud = tolua_touserdata(a_SrcLuaState, i, NULL);
|
||||
tolua_pushusertype(m_LuaState, ud, type);
|
||||
}
|
||||
default:
|
||||
{
|
||||
LOGWARNING("%s: Unsupported value: '%s' at stack position %d. Can only copy numbers, strings, bools and classes!",
|
||||
__FUNCTION__, lua_typename(a_SrcLuaState, t), i
|
||||
);
|
||||
a_SrcLuaState.LogStack("Stack where copying failed:");
|
||||
lua_pop(m_LuaState, i - a_SrcStart);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return a_SrcEnd - a_SrcStart + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cLuaState::ToString(int a_StackPos, AString & a_String)
|
||||
{
|
||||
size_t len;
|
||||
const char * s = lua_tolstring(m_LuaState, a_StackPos, &len);
|
||||
if (s != NULL)
|
||||
{
|
||||
a_String.assign(s, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cLuaState::LogStack(const char * a_Header)
|
||||
{
|
||||
LogStack(m_LuaState, 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--)
|
||||
{
|
||||
AString Value;
|
||||
int Type = lua_type(a_LuaState, i);
|
||||
switch (Type)
|
||||
{
|
||||
case LUA_TBOOLEAN: Value.assign((lua_toboolean(a_LuaState, i) != 0) ? "true" : "false"); break;
|
||||
case LUA_TLIGHTUSERDATA: Printf(Value, "%p", lua_touserdata(a_LuaState, i)); break;
|
||||
case LUA_TNUMBER: Printf(Value, "%f", (double)lua_tonumber(a_LuaState, i)); break;
|
||||
case LUA_TSTRING: Printf(Value, "%s", lua_tostring(a_LuaState, i)); break;
|
||||
default: break;
|
||||
}
|
||||
LOGD(" Idx %d: type %d (%s) %s", i, Type, lua_typename(a_LuaState, Type), Value.c_str());
|
||||
} // for i - stack idx
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user