1
0

LuaState refactoring: using templates for hook function calls.

This simplifies calling Lua functions considerably, it's almost like calling a C++ function, only with an extra argument to delimit args from returned values.
This commit is contained in:
madmaxoft 2013-08-08 14:08:21 +02:00
parent 6c54650b27
commit 198b221997
4 changed files with 668 additions and 793 deletions

View File

@ -32,6 +32,12 @@ extern "C"
const cLuaState::cRet cLuaState::Return;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cLuaState:
@ -272,7 +278,20 @@ bool cLuaState::PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnNam
void cLuaState::PushStringVector(const AStringVector & a_Vector)
void cLuaState::Push(const AString & a_String)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushcppstring(m_LuaState, a_String);
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(const AStringVector & a_Vector)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -305,7 +324,7 @@ void cLuaState::PushUserType(void * a_Object, const char * a_Type)
void cLuaState::PushNumber(int a_Value)
void cLuaState::Push(int a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -318,7 +337,7 @@ void cLuaState::PushNumber(int a_Value)
void cLuaState::PushNumber(double a_Value)
void cLuaState::Push(double a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -331,7 +350,7 @@ void cLuaState::PushNumber(double a_Value)
void cLuaState::PushString(const char * a_Value)
void cLuaState::Push(const char * a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -344,7 +363,7 @@ void cLuaState::PushString(const char * a_Value)
void cLuaState::PushBool(bool a_Value)
void cLuaState::Push(bool a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -357,7 +376,7 @@ void cLuaState::PushBool(bool a_Value)
void cLuaState::PushObject(cWorld * a_World)
void cLuaState::Push(cWorld * a_World)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -370,7 +389,7 @@ void cLuaState::PushObject(cWorld * a_World)
void cLuaState::PushObject(cPlayer * a_Player)
void cLuaState::Push(cPlayer * a_Player)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -383,7 +402,20 @@ void cLuaState::PushObject(cPlayer * a_Player)
void cLuaState::PushObject(cEntity * a_Entity)
void cLuaState::Push(const cPlayer * a_Player)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(cEntity * a_Entity)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -396,7 +428,7 @@ void cLuaState::PushObject(cEntity * a_Entity)
void cLuaState::PushObject(cMonster * a_Monster)
void cLuaState::Push(cMonster * a_Monster)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -409,7 +441,7 @@ void cLuaState::PushObject(cMonster * a_Monster)
void cLuaState::PushObject(cItem * a_Item)
void cLuaState::Push(cItem * a_Item)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -422,7 +454,7 @@ void cLuaState::PushObject(cItem * a_Item)
void cLuaState::PushObject(cItems * a_Items)
void cLuaState::Push(cItems * a_Items)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -435,7 +467,7 @@ void cLuaState::PushObject(cItems * a_Items)
void cLuaState::PushObject(cClientHandle * a_Client)
void cLuaState::Push(cClientHandle * a_Client)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -448,7 +480,7 @@ void cLuaState::PushObject(cClientHandle * a_Client)
void cLuaState::PushObject(cPickup * a_Pickup)
void cLuaState::Push(cPickup * a_Pickup)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@ -461,6 +493,91 @@ void cLuaState::PushObject(cPickup * a_Pickup)
void cLuaState::Push(cChunkDesc * a_ChunkDesc)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_ChunkDesc, "cChunkDesc");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(const cCraftingGrid * a_Grid)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(const cCraftingRecipe * a_Recipe)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(TakeDamageInfo * a_TDI)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_TDI, "TakeDamageInfo");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::GetReturn(int a_StackPos, bool & a_ReturnedVal)
{
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0);
}
void cLuaState::GetReturn(int a_StackPos, AString & a_ReturnedVal)
{
if (lua_isstring(m_LuaState, a_StackPos))
{
a_ReturnedVal = tolua_tocppstring(m_LuaState, a_StackPos, a_ReturnedVal.c_str());
}
}
void cLuaState::GetReturn(int a_StackPos, int & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
a_ReturnedVal = (int)tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal);
}
}
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first

View File

@ -41,6 +41,10 @@ class cItem;
class cItems;
class cClientHandle;
class cPickup;
class cChunkDesc;
class cCraftingGrid;
class cCraftingRecipe;
struct TakeDamageInfo;
@ -69,6 +73,14 @@ public:
cLuaState & m_LuaState;
int m_Ref;
} ;
/// A dummy class that's used only to delimit function args from return values for cLuaState::Call()
class cRet
{
} ;
static const cRet Return; // Use this constant to delimit function args from return values for cLuaState::Call()
/** Creates a new instance. The LuaState is not initialized.
@ -124,33 +136,358 @@ public:
*/
bool PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName);
/// Pushes a string vector, as a table, onto the stack
void PushStringVector(const AStringVector & a_Vector);
/// Pushes a usertype of the specified class type onto the stack
void PushUserType(void * a_Object, const char * a_Type);
// Push a value onto the stack
void Push(const AString & a_String);
void Push(const AStringVector & a_Vector);
void Push(int a_Value);
void Push(double a_Value);
void Push(const char * a_Value);
void Push(bool a_Value);
void Push(cWorld * a_World);
void Push(cPlayer * a_Player);
void Push(const cPlayer * a_Player);
void Push(cEntity * a_Entity);
void Push(cMonster * a_Monster);
void Push(cItem * a_Item);
void Push(cItems * a_Items);
void Push(cClientHandle * a_ClientHandle);
void Push(cPickup * a_Pickup);
void Push(cChunkDesc * a_ChunkDesc);
void Push(const cCraftingGrid * a_Grid);
void Push(const cCraftingRecipe * a_Recipe);
void Push(TakeDamageInfo * a_TDI);
/// Pushes an integer onto the stack
void PushNumber(int a_Value);
/// Call any 1-param 0-return Lua function in a single line:
template<
typename ArgT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
return CallFunction(0);
}
/// Call any 1-param 1-return Lua function in a single line:
template<
typename ArgT1, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Call any 2-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Call any 3-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Pushes a double onto the stack
void PushNumber(double a_Value);
/// Call any 4-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Pushes a string onto the stack
void PushString(const char * a_Value);
/// Call any 5-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
Push(a_Arg5);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Pushes a bool onto the stack
void PushBool(bool a_Value);
/// Call any 6-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
Push(a_Arg5);
Push(a_Arg6);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
// Special family of functions that do PushUserType internally, but require one less parameter
void PushObject(cWorld * a_World);
void PushObject(cPlayer * a_Player);
void PushObject(cEntity * a_Entity);
void PushObject(cMonster * a_Monster);
void PushObject(cItem * a_Item);
void PushObject(cItems * a_Items);
void PushObject(cClientHandle * a_ClientHandle);
void PushObject(cPickup * a_Pickup);
/// Call any 7-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
typename ArgT7, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
Push(a_Arg5);
Push(a_Arg6);
Push(a_Arg7);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Call any 8-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
typename ArgT7, typename ArgT8, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
Push(a_Arg5);
Push(a_Arg6);
Push(a_Arg7);
Push(a_Arg8);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Call any 9-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
typename ArgT7, typename ArgT8, typename ArgT9, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
Push(a_Arg5);
Push(a_Arg6);
Push(a_Arg7);
Push(a_Arg8);
Push(a_Arg9);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Call any 10-param 1-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
typename ArgT7, typename ArgT8, typename ArgT9, typename ArgT10, typename RetT1
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, ArgT10 a_Arg10, const cRet & a_Mark, RetT1 & a_Ret1)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
Push(a_Arg5);
Push(a_Arg6);
Push(a_Arg7);
Push(a_Arg8);
Push(a_Arg9);
Push(a_Arg10);
if (!CallFunction(1))
{
return false;
}
GetReturn(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
/// Call any 2-param 2-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename RetT1, typename RetT2
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
if (!CallFunction(2))
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
/// Call any 9-param 5-return Lua function in a single line:
template<
typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
typename ArgT6, typename ArgT7, typename ArgT8, typename ArgT9,
typename RetT1, typename RetT2, typename RetT3, typename RetT4, typename RetT5
>
bool Call(const char * a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3, RetT4 & a_Ret4, RetT5 & a_Ret5)
{
if (!PushFunction(a_FnName))
{
return false;
}
Push(a_Arg1);
Push(a_Arg2);
Push(a_Arg3);
Push(a_Arg4);
Push(a_Arg5);
Push(a_Arg6);
Push(a_Arg7);
Push(a_Arg8);
Push(a_Arg9);
if (!CallFunction(5))
{
return false;
}
GetReturn(-5, a_Ret1);
GetReturn(-4, a_Ret2);
GetReturn(-3, a_Ret3);
GetReturn(-2, a_Ret4);
GetReturn(-1, a_Ret5);
lua_pop(m_LuaState, 5);
return true;
}
/// Retrieve value returned at a_StackPos, if it is a valid bool. If not, a_ReturnedVal is unchanged
void GetReturn(int a_StackPos, bool & a_ReturnedVal);
/// Retrieve value returned at a_StackPos, if it is a valid string. If not, a_ReturnedVal is unchanged
void GetReturn(int a_StackPos, AString & a_ReturnedVal);
/// Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged
void GetReturn(int a_StackPos, int & a_ReturnedVal);
/**
Calls the function that has been pushed onto the stack by PushFunction(),

View File

@ -85,7 +85,7 @@ static int tolua_StringSplit(lua_State * tolua_S)
std::string delim = (std::string)tolua_tocppstring(LuaState, 2, 0);
AStringVector Split = StringSplit(str, delim);
LuaState.PushStringVector(Split);
LuaState.Push(Split);
return 1;
}
@ -1504,11 +1504,11 @@ public:
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
m_LuaState.PushNumber(a_BlockType);
m_LuaState.PushNumber(a_BlockMeta);
m_LuaState.Push(a_BlockX);
m_LuaState.Push(a_BlockY);
m_LuaState.Push(a_BlockZ);
m_LuaState.Push(a_BlockType);
m_LuaState.Push(a_BlockMeta);
if (!m_LuaState.CallFunction(1))
{
return false;
@ -1529,9 +1529,9 @@ public:
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
m_LuaState.Push(a_BlockX);
m_LuaState.Push(a_BlockY);
m_LuaState.Push(a_BlockZ);
if (!m_LuaState.CallFunction(1))
{
return false;
@ -1552,9 +1552,9 @@ public:
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
m_LuaState.Push(a_BlockX);
m_LuaState.Push(a_BlockY);
m_LuaState.Push(a_BlockZ);
if (!m_LuaState.CallFunction(1))
{
return false;
@ -1575,9 +1575,9 @@ public:
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
m_LuaState.Push(a_BlockX);
m_LuaState.Push(a_BlockY);
m_LuaState.Push(a_BlockZ);
if (!m_LuaState.CallFunction(1))
{
return false;

File diff suppressed because it is too large Load Diff