From 10a0e290ac07524dc129cc2b227b0f9e95df0f8e Mon Sep 17 00:00:00 2001 From: Ben Beltran Date: Mon, 16 Apr 2012 09:39:52 -0500 Subject: first commit --- LuaScript.cpp | 440 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 LuaScript.cpp (limited to 'LuaScript.cpp') diff --git a/LuaScript.cpp b/LuaScript.cpp new file mode 100644 index 0000000..a47d5c4 --- /dev/null +++ b/LuaScript.cpp @@ -0,0 +1,440 @@ +// --------------------------------------------------------------------------- +// FILE NAME : LuaScript.cpp +// --------------------------------------------------------------------------- +// DESCRIPTION : +// +// Simple debugging routines +// +// --------------------------------------------------------------------------- +// VERSION : 1.00 +// DATE : 1-Sep-2005 +// AUTHOR : Richard Shephard +// --------------------------------------------------------------------------- +// LIBRARY INCLUDE FILES +#include +#include "luainc.h" +#include "luascript.h" +#include "luarestorestack.h" +#include "luathis.h" +// --------------------------------------------------------------------------- + +#define BEGIN_LUA_CHECK(vm) lua_State *state = (lua_State *) vm; \ + if (vm.Ok ()) { +#define END_LUA_CHECK } + + +//============================================================================ +// int LuaCallback +//--------------------------------------------------------------------------- +// Lua C-API calling that figures out which object to hand over to +// +// Parameter Dir Description +// --------- --- ----------- +// lua IN State variable +// +// Return +// ------ +// Number of return varaibles on the stack +// +// Comments +// -------- +// This is the function lua calls for each C-Function that is +// registered with lua. At the time of registering the function +// with lua, we make lua record the method "number" so we can +// know what method was actually called. The lua stack is the +// following structure: +// 0: 'this' (table) +// 1 - ...: parameters passed in +// +//============================================================================ +static int LuaCallback (lua_State *lua) +{ + // Locate the psudo-index for the function number + int iNumberIdx = lua_upvalueindex (1); + int nRetsOnStack = 0; + + bool fSuccess = false; + + // Check for the "this" table + if (lua_istable (lua, 1)) + { + // Found the "this" table. The object pointer is at the index 0 + lua_rawgeti (lua, 1, 0); + + if (lua_islightuserdata (lua, -1)) + { + // Found the pointer, need to cast it + CLuaScript *pThis = (CLuaScript *) lua_touserdata (lua, -1); + + // Get the method index + int iMethodIdx = (int) lua_tonumber (lua, iNumberIdx); + + // Check that the method is correct index + assert (!(iMethodIdx > pThis->methods ())); + + // Reformat the stack so our parameters are correct + // Clean up the "this" table + lua_remove (lua, 1); + // Clean up the pThis pointer + lua_remove (lua, -1); + + // Call the class + nRetsOnStack = pThis->ScriptCalling (pThis->vm (), iMethodIdx); + + fSuccess = true; + } + } + + if (fSuccess == false) + { + lua_pushstring (lua, "LuaCallback -> Failed to call the class function"); + lua_error (lua); + } + + // Number of return variables + return nRetsOnStack; +} + + +//============================================================================ +// CLuaScript::CLuaScript +//--------------------------------------------------------------------------- +// Constructor. Sets up the lua stack and the "this" table +// +// Parameter Dir Description +// --------- --- ----------- +// CLuaVirtualMachine IN VM to run on +// +// Return +// ------ +// None. +// +//============================================================================ +CLuaScript::CLuaScript (CLuaVirtualMachine& vm) + : m_vm (vm), m_nMethods (0), m_iThisRef (0), m_nArgs (0) +{ + BEGIN_LUA_CHECK (vm) + // Create a reference to the "this" table. Each reference is unique + lua_newtable (state); + m_iThisRef = luaL_ref (state, LUA_REGISTRYINDEX); + + // Save the "this" table to index 0 of the "this" table + CLuaRestoreStack rs (vm); + lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef); + lua_pushlightuserdata (state, (void *) this); + lua_rawseti (state, -2, 0); + END_LUA_CHECK +} + +//============================================================================ +// CLuaScript::~CLuaScript +//--------------------------------------------------------------------------- +// Destructor +// +// Parameter Dir Description +// --------- --- ----------- +// None. +// +// Return +// ------ +// None. +// +//============================================================================ +CLuaScript::~CLuaScript (void) +{ + CLuaRestoreStack rs (m_vm); + + BEGIN_LUA_CHECK (m_vm) + // Get the reference "this" table + lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef); + + // Clear index 0 + lua_pushnil (state); + lua_rawseti (state, -2, 0); + END_LUA_CHECK + +} + +//============================================================================ +// bool CLuaScript::CompileBuffer +//--------------------------------------------------------------------------- +// Compiles a given buffer +// +// Parameter Dir Description +// --------- --- ----------- +// pbBuffer IN Data buffer +// szLen IN Length of buffer +// +// Return +// ------ +// Success +// +//============================================================================ +bool CLuaScript::CompileBuffer (unsigned char *pbBuffer, size_t szLen) +{ + assert (pbBuffer != NULL && "CLuaScript::CompileBuffer -> pbBuffer == NULL"); + assert (szLen != 0 && "CLuaScript::CompileBuffer -> szLen == 0"); + assert (m_vm.Ok () && "VM Not OK"); + + // Make sure we have the correct "this" table + CLuaThis luaThis (m_vm, m_iThisRef); + + return m_vm.RunBuffer (pbBuffer, szLen); +} + +//============================================================================ +// bool CLuaScript::CompileBuffer +//--------------------------------------------------------------------------- +// Compiles a given file +// +// Parameter Dir Description +// --------- --- ----------- +// strFilename IN File name to compile +// +// Return +// ------ +// Success +// +//============================================================================ +bool CLuaScript::CompileFile (const char *strFilename) +{ + assert (strFilename != NULL && "CLuaScript::CompileFile -> strFilename == NULL"); + assert (m_vm.Ok () && "VM Not OK"); + + // Make sure we have the correct "this" table + CLuaThis luaThis (m_vm, m_iThisRef); + + return m_vm.RunFile (strFilename); +} + +//============================================================================ +// int CLuaScript::RegisterFunction +//--------------------------------------------------------------------------- +// Registers a function with Lua +// +// Parameter Dir Description +// --------- --- ----------- +// strFuncName IN Function name +// +// Return +// ------ +// Success +// +//============================================================================ +int CLuaScript::RegisterFunction (const char *strFuncName) +{ + assert (strFuncName != NULL && "CLuaScript::RegisterFunction -> strFuncName == NULL"); + assert (m_vm.Ok () && "VM Not OK"); + + int iMethodIdx = -1; + + CLuaRestoreStack rs (m_vm); + + BEGIN_LUA_CHECK (m_vm) + iMethodIdx = ++m_nMethods; + + // Register a function with the lua script. Added it to the "this" table + lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef); + + // Push the function and parameters + lua_pushstring (state, strFuncName); + lua_pushnumber (state, (lua_Number) iMethodIdx); + lua_pushcclosure (state, LuaCallback, 1); + lua_settable (state, -3); + + END_LUA_CHECK + + return iMethodIdx; +} + +//============================================================================ +// bool CLuaScript::SelectScriptFunction +//--------------------------------------------------------------------------- +// Selects a script function to run +// +// Parameter Dir Description +// --------- --- ----------- +// strFuncName IN Function name +// +// Return +// ------ +// Success +// +//============================================================================ +bool CLuaScript::SelectScriptFunction (const char *strFuncName) +{ + assert (strFuncName != NULL && "CLuaScript::SelectScriptFunction -> strFuncName == NULL"); + assert (m_vm.Ok () && "VM Not OK"); + + bool fSuccess = true; + + BEGIN_LUA_CHECK (m_vm) + // Look up function name + lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef); + lua_pushstring (state, strFuncName); + lua_rawget (state, -2); + lua_remove (state, -2); + + // Put the "this" table back + lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef); + + // Check that we have a valid function + if (!lua_isfunction (state, -2)) + { + fSuccess = false; + lua_pop (state, 2); + } + else + { + m_nArgs = 0; + m_strFunctionName = strFuncName; + } + END_LUA_CHECK + + return fSuccess; +} + +//============================================================================ +// bool CLuaScript::ScriptHasFunction +//--------------------------------------------------------------------------- +// Checks to see if a function exists +// +// Parameter Dir Description +// --------- --- ----------- +// strScriptName IN Function name +// +// Return +// ------ +// Success +// +//============================================================================ +bool CLuaScript::ScriptHasFunction (const char *strScriptName) +{ + assert (strScriptName != NULL && "CLuaScript::ScriptHasFunction -> strScriptName == NULL"); + assert (m_vm.Ok () && "VM Not OK"); + + CLuaRestoreStack rs (m_vm); + + bool fFoundFunc = false; + + BEGIN_LUA_CHECK (m_vm) + lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef); + lua_pushstring (state, strScriptName); + lua_rawget (state, -2); + lua_remove (state, -2); + + if (lua_isfunction (state, -1)) + { + fFoundFunc = true; + } + END_LUA_CHECK + + return fFoundFunc; +} + +//============================================================================ +// void CLuaScript::AddParam +//--------------------------------------------------------------------------- +// Adds a parameter to the parameter list +// +// Parameter Dir Description +// --------- --- ----------- +// string IN string param +// +// Return +// ------ +// None. +// +//============================================================================ +void CLuaScript::AddParam (char *string) +{ + assert (string != NULL && "CLuaScript::AddParam -> string == NULL"); + assert (m_vm.Ok () && "VM Not OK"); + + BEGIN_LUA_CHECK (m_vm) + lua_pushstring (state, string); + ++m_nArgs; + END_LUA_CHECK +} + +//============================================================================ +// void CLuaScript::AddParam +//--------------------------------------------------------------------------- +// Adds a parameter to the parameter list +// +// Parameter Dir Description +// --------- --- ----------- +// iInt IN int param +// +// Return +// ------ +// None. +// +//============================================================================ +void CLuaScript::AddParam (int iInt) +{ + assert (m_vm.Ok () && "VM Not OK"); + + BEGIN_LUA_CHECK (m_vm) + lua_pushnumber (state, (lua_Number) iInt); + ++m_nArgs; + END_LUA_CHECK +} + +//============================================================================ +// void CLuaScript::AddParam +//--------------------------------------------------------------------------- +// Adds a parameter to the parameter list +// +// Parameter Dir Description +// --------- --- ----------- +// fFloat IN float param +// +// Return +// ------ +// None. +// +//============================================================================ +void CLuaScript::AddParam (float fFloat) +{ + assert (m_vm.Ok () && "VM Not OK"); + + BEGIN_LUA_CHECK (m_vm) + lua_pushnumber (state, (lua_Number) fFloat); + ++m_nArgs; + END_LUA_CHECK +} + +//============================================================================ +// bool CLuaScript::Go +//--------------------------------------------------------------------------- +// Runs the selected script function +// +// Parameter Dir Description +// --------- --- ----------- +// nReturns IN Number of expected returns +// +// Return +// ------ +// None. +// +//============================================================================ +bool CLuaScript::Go (int nReturns /* = 0 */) +{ + assert (m_vm.Ok () && "VM Not OK"); + + // At this point there should be a parameters and a function on the + // Lua stack. Each function get a "this" parameter as default and is + // pushed onto the stack when the method is selected + + bool fSuccess = m_vm.CallFunction (m_nArgs + 1, nReturns); + + if (fSuccess == true && nReturns > 0) + { + // Check for returns + HandleReturns (m_vm, m_strFunctionName); + lua_pop ((lua_State *) m_vm, nReturns); + } + + return fSuccess; +} \ No newline at end of file -- cgit