cLuaState has reference management, param checking and a fixed destructor.
References are now managed as RAII objects, cLuaState::cRef. Destructor now calls correct function, either Close() or Detach(), based on the owned-ness of the lua_State *.
This commit is contained in:
parent
c55fabb5ad
commit
9b839aa32e
@ -63,7 +63,14 @@ cLuaState::~cLuaState()
|
|||||||
{
|
{
|
||||||
if (IsValid())
|
if (IsValid())
|
||||||
{
|
{
|
||||||
Close();
|
if (m_IsOwned)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +243,35 @@ bool cLuaState::PushFunctionFromRegistry(int a_FnRef)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cLuaState::PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
|
||||||
|
|
||||||
|
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_TableRef); // Get the table ref
|
||||||
|
if (!lua_istable(m_LuaState, -1))
|
||||||
|
{
|
||||||
|
// Not a table, bail out
|
||||||
|
lua_pop(m_LuaState, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lua_getfield(m_LuaState, -1, a_FnName);
|
||||||
|
if (lua_isnil(m_LuaState, -1) || !lua_isfunction(m_LuaState, -1))
|
||||||
|
{
|
||||||
|
// Not a valid function, bail out
|
||||||
|
lua_pop(m_LuaState, 2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lua_remove(m_LuaState, -2); // Remove the table ref from the stack
|
||||||
|
m_CurrentFunctionName = "<table_callback>";
|
||||||
|
m_NumCurrentFunctionArgs = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::PushStringVector(const AStringVector & a_Vector)
|
void cLuaState::PushStringVector(const AStringVector & a_Vector)
|
||||||
{
|
{
|
||||||
ASSERT(IsValid());
|
ASSERT(IsValid());
|
||||||
@ -434,6 +470,125 @@ bool cLuaState::CallFunction(int a_NumResults)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cLuaState::CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
|
if (a_EndParam < 0)
|
||||||
|
{
|
||||||
|
a_EndParam = a_StartParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
tolua_Error tolua_err;
|
||||||
|
for (int i = a_StartParam; i <= a_EndParam; i++)
|
||||||
|
{
|
||||||
|
if (tolua_isusertype(m_LuaState, i, a_UserType, 0, &tolua_err))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Not the correct parameter
|
||||||
|
lua_Debug entry;
|
||||||
|
VERIFY(lua_getstack(m_LuaState, 0, &entry));
|
||||||
|
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
|
||||||
|
AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
|
||||||
|
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
|
||||||
|
return false;
|
||||||
|
} // for i - Param
|
||||||
|
|
||||||
|
// All params checked ok
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cLuaState::CheckParamTable(int a_StartParam, int a_EndParam)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
|
if (a_EndParam < 0)
|
||||||
|
{
|
||||||
|
a_EndParam = a_StartParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
tolua_Error tolua_err;
|
||||||
|
for (int i = a_StartParam; i <= a_EndParam; i++)
|
||||||
|
{
|
||||||
|
if (tolua_istable(m_LuaState, i, 0, &tolua_err))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Not the correct parameter
|
||||||
|
lua_Debug entry;
|
||||||
|
VERIFY(lua_getstack(m_LuaState, 0, &entry));
|
||||||
|
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
|
||||||
|
AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
|
||||||
|
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
|
||||||
|
return false;
|
||||||
|
} // for i - Param
|
||||||
|
|
||||||
|
// All params checked ok
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cLuaState::CheckParamNumber(int a_StartParam, int a_EndParam)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
|
if (a_EndParam < 0)
|
||||||
|
{
|
||||||
|
a_EndParam = a_StartParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
tolua_Error tolua_err;
|
||||||
|
for (int i = a_StartParam; i <= a_EndParam; i++)
|
||||||
|
{
|
||||||
|
if (tolua_isnumber(m_LuaState, i, 0, &tolua_err))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Not the correct parameter
|
||||||
|
lua_Debug entry;
|
||||||
|
VERIFY(lua_getstack(m_LuaState, 0, &entry));
|
||||||
|
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
|
||||||
|
AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
|
||||||
|
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
|
||||||
|
return false;
|
||||||
|
} // for i - Param
|
||||||
|
|
||||||
|
// All params checked ok
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cLuaState::CheckParamEnd(int a_Param)
|
||||||
|
{
|
||||||
|
tolua_Error tolua_err;
|
||||||
|
if (tolua_isnoobj(m_LuaState, a_Param, &tolua_err))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Not the correct parameter
|
||||||
|
lua_Debug entry;
|
||||||
|
VERIFY(lua_getstack(m_LuaState, 0, &entry));
|
||||||
|
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
|
||||||
|
AString ErrMsg = Printf("#ferror in function '%s': Too many arguments.", (entry.name != NULL) ? entry.name : "?");
|
||||||
|
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cLuaState::ReportErrors(int a_Status)
|
bool cLuaState::ReportErrors(int a_Status)
|
||||||
{
|
{
|
||||||
return ReportErrors(m_LuaState, a_Status);
|
return ReportErrors(m_LuaState, a_Status);
|
||||||
@ -459,3 +614,33 @@ bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cLuaState::cRef:
|
||||||
|
|
||||||
|
cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) :
|
||||||
|
m_LuaState(a_LuaState)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cLuaState::cRef::~cRef()
|
||||||
|
{
|
||||||
|
ASSERT(m_LuaState.IsValid());
|
||||||
|
|
||||||
|
if (IsValid())
|
||||||
|
{
|
||||||
|
luaL_unref(m_LuaState, LUA_REGISTRYINDEX, m_Ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@ Calling a Lua function is done by pushing the function, either by PushFunction()
|
|||||||
then pushing the arguments (PushString(), PushNumber(), PushUserData() etc.) and finally
|
then pushing the arguments (PushString(), PushNumber(), PushUserData() etc.) and finally
|
||||||
executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the
|
executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the
|
||||||
function (for logging purposes), which makes the call less error-prone.
|
function (for logging purposes), which makes the call less error-prone.
|
||||||
|
|
||||||
|
Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to
|
||||||
|
any Lua object across several function calls; usually this is used for callbacks. The class is RAII-like, with
|
||||||
|
automatic resource management.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -20,12 +24,14 @@ function (for logging purposes), which makes the call less error-prone.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "lauxlib.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fwd: lua.h
|
|
||||||
struct lua_State;
|
|
||||||
|
|
||||||
class cWorld;
|
class cWorld;
|
||||||
class cPlayer;
|
class cPlayer;
|
||||||
@ -39,9 +45,31 @@ class cPickup;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Encapsulates a Lua state and provides some syntactic sugar for common operations
|
||||||
class cLuaState
|
class cLuaState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// Used for storing references to object in the global registry
|
||||||
|
class cRef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Creates a reference in the specified LuaState for object at the specified StackPos
|
||||||
|
cRef(cLuaState & a_LuaState, int a_StackPos);
|
||||||
|
~cRef();
|
||||||
|
|
||||||
|
/// Returns true if the reference is valid
|
||||||
|
bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
|
||||||
|
|
||||||
|
/// Allows to use this class wherever an int (i. e. ref) is to be used
|
||||||
|
operator int(void) { return m_Ref; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cLuaState & m_LuaState;
|
||||||
|
int m_Ref;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new instance. The LuaState is not initialized.
|
/** Creates a new instance. The LuaState is not initialized.
|
||||||
a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
|
a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
|
||||||
or "LuaScript" for the cLuaScript template
|
or "LuaScript" for the cLuaScript template
|
||||||
@ -90,6 +118,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool PushFunctionFromRegistry(int a_FnRef);
|
bool PushFunctionFromRegistry(int a_FnRef);
|
||||||
|
|
||||||
|
/** Pushes a function that is stored in a table ref.
|
||||||
|
Returns true if successful, false on failure. Doesn't log failure.
|
||||||
|
*/
|
||||||
|
bool PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName);
|
||||||
|
|
||||||
/// Pushes a string vector, as a table, onto the stack
|
/// Pushes a string vector, as a table, onto the stack
|
||||||
void PushStringVector(const AStringVector & a_Vector);
|
void PushStringVector(const AStringVector & a_Vector);
|
||||||
|
|
||||||
@ -123,7 +156,19 @@ public:
|
|||||||
Returns true if successful, logs a warning on failure.
|
Returns true if successful, logs a warning on failure.
|
||||||
*/
|
*/
|
||||||
bool CallFunction(int a_NumReturnValues);
|
bool CallFunction(int a_NumReturnValues);
|
||||||
|
|
||||||
|
/// Returns true if the specified parameters on the stack are of the specified usertype; also logs warning if not
|
||||||
|
bool CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam = -1);
|
||||||
|
|
||||||
|
/// Returns true if the specified parameters on the stack are a table; also logs warning if not
|
||||||
|
bool CheckParamTable(int a_StartParam, int a_EndParam = -1);
|
||||||
|
|
||||||
|
/// Returns true if the specified parameters on the stack are a number; also logs warning if not
|
||||||
|
bool CheckParamNumber(int a_StartParam, int a_EndParam = -1);
|
||||||
|
|
||||||
|
/// Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters)
|
||||||
|
bool CheckParamEnd(int a_Param);
|
||||||
|
|
||||||
/// If the status is nonzero, prints the text on the top of Lua stack and returns true
|
/// If the status is nonzero, prints the text on the top of Lua stack and returns true
|
||||||
bool ReportErrors(int status);
|
bool ReportErrors(int status);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user