#include "ScriptVM.h"
#include "IOServer.h"
#include "FileStream.h"
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
#include "tolua++.h"
#include<stdio.h>
#include <assert.h>
#include <sstream>
#define DEBUG_STACK 0
//end of tolua bind declare
extern void tolua_open_binding(lua_State * pLua);
static void stackDump(lua_State *pLua);
//sigslot::signal1<const char*> ScriptVM::LuaPrinted;
//error_msg handling function
static void error_msg(
bool bUseAssert,
const char * pacFmt,
)
{
//#if defined(_DEBUG)
char acTemp[2048];
va_list args;
va_start(args, pacFmt);
vsprintf_s(acTemp, pacFmt, args);
va_end(args);
if (bUseAssert)
{
assert( acTemp);
}
//#endif
}
void report_last_error(lua_State *pLua,
bool bUseAssert)
{
lua_getglobal(pLua, "_ALERT");
error_msg(bUseAssert, "%s\n", lua_tostring(pLua, -2));
error_msg(bUseAssert, "%s\n", lua_tostring(pLua, -1));
lua_pop(pLua, 2);
/* remove error_msg message and _ALERT */}
std::
string & std_string_format(std::
string & _str,
const char * _Format,
) {
std::
string tmp;
va_list marker = NULL;
va_start(marker, _Format);
size_t num_of_chars = _vscprintf(_Format, marker);
if (num_of_chars > tmp.capacity()) {
tmp.resize(num_of_chars + 1);
}
vsprintf_s((
char *)tmp.data(), tmp.capacity(), _Format, marker);
va_end(marker);
_str = tmp.c_str();
return _str;
}
ScriptVM::ScriptVM(
void)
{
}
ScriptVM::~ScriptVM(
void)
{
}
static int PrintStringList(lua_State * pLua) {
int n = lua_gettop(pLua);
/* number of arguments */ int i;
lua_getglobal(pLua, "tostring");
std::
string out;
for (i = 1; i <= n; i++) {
const char *s;
lua_pushvalue(pLua, -1);
/* function to be called */ lua_pushvalue(pLua, i);
/* value to print */ lua_call(pLua, 1, 1);
s = lua_tostring(pLua, -1);
/* get result */ if (s == NULL)
return luaL_error(pLua, "`tostring' must return a string to `print'");
if (i > 1)
{
out += "\t";
out += s;
}
else out += s;
lua_pop(pLua, 1);
/* pop result */ }
out += "\n";
return 0;
}
bool ScriptVM::Init(
void)
{
m_pLua = luaL_newstate();
lua_cpcall(m_pLua, luaopen_base, 0);
lua_cpcall(m_pLua, luaopen_io, 0);
lua_cpcall(m_pLua, luaopen_string, 0);
lua_cpcall(m_pLua, luaopen_table, 0);
lua_cpcall(m_pLua, luaopen_math, 0);
lua_cpcall(m_pLua, luaopen_debug, 0);
lua_cpcall(m_pLua, luaopen_os, 0);
lua_cpcall(m_pLua, luaopen_package, 0);
//luaopen_base(m_pLua);
//luaopen_io(m_pLua);
//luaopen_table(m_pLua);
//luaopen_math(m_pLua);
//luaopen_string(m_pLua);
//luaopen_debug(m_pLua);
//tolua_open_binding(m_pLua);
//lua_setgcthreshold(m_pLua, 200); //200k garbage collection threshold
lua_register(m_pLua, "print", PrintStringList);
//lua_register(m_pLua, "dofile", OverrideDofile);
return true;
}
void ScriptVM::Destroy(
void)
{
lua_close(m_pLua);
}
void ScriptVM::ExecuteScriptFile(
const char * sScriptName,
bool bForceReload
/* = false*/,
bool bAssertOnError
/*= true*/)
{
int nSize1 = lua_gettop(m_pLua);
//get chunk name as modified script name
std::
string sChunkName(sScriptName);
for (unsigned
int i = 0; i < sChunkName.length(); i++)
{
if (sChunkName[i] == '/' || sChunkName[i] == '.')
sChunkName[i] = '_';
}
//get the chunk global
lua_getglobal(m_pLua, sChunkName.c_str());
if (bForceReload || !lua_isfunction(m_pLua, -1))
//if force reload or not found
{
//load it first
unsigned
char * pBuff;
int nSize;
if (LoadFileToBuffer(sScriptName, pBuff, nSize, bAssertOnError))
{
luaL_loadbuffer(m_pLua, (
char *)pBuff, nSize, sScriptName);
delete[] pBuff;
// luaL_loadfile(m_pLua, sScriptName);
lua_setglobal(m_pLua, sChunkName.c_str());
lua_getglobal(m_pLua, sChunkName.c_str());
}
else goto failed;
}
if (lua_pcall(m_pLua, 0, 0, 0) != 0)
{
error_msg(bAssertOnError, "error executing script file %s: ", sScriptName);
report_last_error(m_pLua, bAssertOnError);
}
failed:
lua_settop(m_pLua, nSize1);
}
void ScriptVM::ExecuteScript(
const char * sScript,
bool bAssertOnError)
{
int status = luaL_loadbuffer(m_pLua, sScript, strlen(sScript), sScript);
if (status)
{
report_last_error(m_pLua, bAssertOnError);
}
else {
status = lua_pcall(m_pLua, 0, LUA_MULTRET, 0);
/* call main */ if (status)
report_last_error(m_pLua, bAssertOnError);
}
}
/*
* Execute Script Function func in the script. copy/pasted from the book "programming in LUA"
*/bool ScriptVM::ExecuteScriptFunc(
const std::vector<
const char *>&modules,
const char * func,
bool bAllowNonexist,
const char * sig,
)
{
bool bIsSuccess =
false;
//PROFILE("ExecuteScriptFunc");
int nSize1 = lua_gettop(m_pLua);
//debug
#if DEBUG_STACK
printf("debug lua: stack size before ExecuteScriptFunc = %d\n", nSize1);
#endif va_list vl;
int narg, nres;
/* number of arguments and results */ va_start(vl, sig);
//get the actual function
if (modules.empty())
//func is global
{
lua_getglobal(m_pLua, func);
if (!lua_isfunction(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid function name: %s\n", func);
goto failed;
}
}
else {
//trace down the modules
std::vector<
const char *>::const_iterator it = modules.begin();
//get the global module name or the actual function name if there is no module
lua_getglobal(m_pLua, *it);
if (!lua_istable(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid table name: %s\n", *it);
goto failed;
}
for (++it; it != modules.end(); ++it)
{
lua_pushstring(m_pLua, *it);
lua_gettable(m_pLua, -2);
if (!lua_istable(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid table name: %s\n", *it);
goto failed;
}
}
//get the func
lua_pushstring(m_pLua, func);
lua_gettable(m_pLua, -2);
if (!lua_isfunction(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid function name: %s\n", func);
goto failed;
}
}
/* push arguments */ narg = 0;
while (*sig) {
/* push arguments */ switch (*sig++) {
case 'd':
/* double argument */ case 'f':
/* float argument */ // NieXu: Treat float as double, same as printf()
lua_pushnumber(m_pLua, va_arg(vl,
double));
break;
case 'i':
/* int argument */ lua_pushnumber(m_pLua, va_arg(vl,
int));
break;
case 's':
/* string argument */ lua_pushstring(m_pLua, va_arg(vl,
char *));
break;
case 'b':
/* boolean argument */ lua_pushboolean(m_pLua, va_arg(vl,
bool));
break;
case 'u':
/* light user data */ lua_pushlightuserdata(m_pLua, va_arg(vl,
void *));
break;
case 't':
/* type user data */ {
void* pData = va_arg(vl,
void *);
const char* sType = va_arg(vl,
const char*);
tolua_pushusertype(m_pLua, pData, sType);
break;
}
case '>':
goto endwhile;
default:
error_msg(
true, "invalid option (%c)\n", *(sig - 1));
goto failed;
}
narg++;
luaL_checkstack(m_pLua, 1, "too many arguments");
}endwhile:
/* do the call */ nres = strlen(sig);
/* number of expected results */ if (lua_pcall(m_pLua, narg, nres, 0) != 0)
/* do the call */ {
report_last_error(m_pLua,
true);
goto failed;
}
/* retrieve results */ nres = -nres;
/* stack index of first result */ while (*sig)
{
/* get results */ switch (*sig++)
{
case 'd':
/* double result */ if (!lua_isnumber(m_pLua, nres))
error_msg(
true, "wrong result type,function name: %s\n", func);
*va_arg(vl,
double *) = lua_tonumber(m_pLua, nres);
break;
case 'f':
/* float result */ if (!lua_isnumber(m_pLua, nres))
error_msg(
true, "wrong result type,function name: %s\n", func);
*va_arg(vl,
float*) = (
float)lua_tonumber(m_pLua, nres);
break;
case 'i':
/* int result */ if (!lua_isnumber(m_pLua, nres))
error_msg(
true, "wrong result type,function name: %s\n", func);
*va_arg(vl,
int *) = (
int)lua_tonumber(m_pLua, nres);
break;
case 's':
/* string result */ if (!lua_isstring(m_pLua, nres))
error_msg(
true, "wrong result type,function name: %s\n", func);
*va_arg(vl, std::
string*) = lua_tostring(m_pLua, nres);
break;
case 'b':
/* boolean argument */ if (!lua_isboolean(m_pLua, nres))
error_msg(
true, "wrong result type,function name: %s\n", func);
*va_arg(vl,
bool *) = (0 != lua_toboolean(m_pLua, nres));
break;
case 'u':
/* light user data */ if (!lua_isuserdata(m_pLua, nres))
error_msg(
true, "wrong result type,function name: %s\n", func);
*va_arg(vl,
void **) = lua_touserdata(m_pLua, nres);
break;
default:
error_msg(
true, "invalid option (%c)\n", *(sig - 1));
}
nres++;
}
bIsSuccess =
true;
failed:
va_end(vl);
//clear the stack
lua_settop(m_pLua, nSize1);
#if DEBUG_STACK
//debug
int nSize2 = lua_gettop(m_pLua);
printf("debug lua: stack size after ExecuteScriptFunc = %d\n", nSize2);
if (nSize1 != nSize2)
stackDump(m_pLua);
#endif return bIsSuccess;
}
void ScriptVM::ExposeGlobalUserdata(
void * va,
const char * name,
const char * type)
{
int nSize1 = lua_gettop(m_pLua);
#if DEBUG_STACK
//debug
printf("debug lua: stack size before ExposeGlobalUserdata = %d\n", nSize1);
#endif tolua_pushusertype(m_pLua, va, type);
lua_setglobal(m_pLua, name);
//clear the stack
lua_settop(m_pLua, nSize1);
#if DEBUG_STACK
//debug
int nSize2 = lua_gettop(m_pLua);
printf("debug lua: stack size after ExposeGlobalUserdata = %d\n", nSize2);
if (nSize1 != nSize2)
stackDump(m_pLua);
#endif}
void * ScriptVM::GetGlobalUserdata(
const char * name,
const char * verify_type
/*= NULL*/)
{
void * pRet = NULL;
int nSize1 = lua_gettop(m_pLua);
int nSize2 = 0;
#if DEBUG_STACK
//debug
printf("debug lua: stack size before GetGlobalUserdata = %d\n", nSize1);
#endif lua_getglobal(m_pLua, name);
//verify type
if (verify_type)
{
tolua_Error tolua_err;
if (
!tolua_isusertype(m_pLua, 1, verify_type, 0, &tolua_err) ||
!tolua_isnoobj(m_pLua, 2, &tolua_err)
)
{
tolua_error(m_pLua, "#ferror in function 'ScriptVM::GetGlobalUserdata'.", &tolua_err);
goto failed;
}
}
pRet = tolua_tousertype(m_pLua, -1, 0);
//clear the stack
lua_settop(m_pLua, nSize1);
#if DEBUG_STACK
//debug
nSize2 = lua_gettop(m_pLua);
printf("debug lua: stack size after GetGlobalUserdata = %d\n", nSize2);
if (nSize1 != nSize2)
stackDump(m_pLua);
#endif return pRet;
failed:
//lua_settop(m_pLua,0);
lua_settop(m_pLua, nSize1);
return NULL;
}
double ScriptVM::GetGlobalNumber(
const char * name)
{
int nSize1 = lua_gettop(m_pLua);
#if DEBUG_STACK
//debug
printf("debug lua: stack size before GetGlobalUserdata = %d\n", nSize1);
#endif lua_getglobal(m_pLua, name);
double ret = tolua_tonumber(m_pLua, -1, 0);
//clear the stack
lua_settop(m_pLua, nSize1);
#if DEBUG_STACK
//debug
int nSize2 = lua_gettop(m_pLua);
printf("debug lua: stack size after GetGlobalUserdata = %d\n", nSize2);
if (nSize1 != nSize2)
stackDump(m_pLua);
#endif return ret;
}
void * ScriptVM::GetUserdata(
const std::vector<
const char *>& modules,
const char * name,
const char * verify_type
/*= NULL*/)
{
void * pRet = NULL;
int nSize1 = lua_gettop(m_pLua);
int nSize2 = 0;
#if DEBUG_STACK
printf("debug lua: stack size before GetUserdata = %d\n", nSize1);
#endif if (modules.empty())
//userdata is global
{
lua_getglobal(m_pLua, name);
}
else {
//trace down the modules
std::vector<
const char *>::const_iterator it = modules.begin();
//get the global module name or the actual function name if there is no module
lua_getglobal(m_pLua, *it);
if (!lua_istable(m_pLua, -1))
{
error_msg(
true, "GetUserdata: Invalid table name: %s\n", *it);
goto failed;
}
for (++it; it != modules.end(); ++it)
{
lua_pushstring(m_pLua, *it);
lua_gettable(m_pLua, -2);
if (!lua_istable(m_pLua, -1))
{
std::vector<
const char *>::const_iterator itMsg = modules.begin();
std::
string sMsg;
for (; itMsg <= it; ++itMsg)
{
sMsg.append(*itMsg);
if (itMsg != it)
{
sMsg.append(".");
}
}
error_msg(
true, "GetUserdata: Invalid table name: %s\n", sMsg.c_str());
goto failed;
}
}
//get the data
lua_pushstring(m_pLua, name);
lua_gettable(m_pLua, -2);
}
//verify type
//if(verify_type)
//{
// tolua_Error tolua_err;
// if (
// !tolua_isusertype(m_pLua,1,verify_type,0,&tolua_err) ||
// !tolua_isnoobj(m_pLua,2,&tolua_err)
// )
// {
// error_msg(m_pLua,"#ferror in function 'ScriptVM:GetUserdata: %s\n", name);
// goto failed;
// }
//}
pRet = tolua_tousertype(m_pLua, -1, 0);
//clear the stack
lua_settop(m_pLua, nSize1);
#if DEBUG_STACK
//debug
nSize2 = lua_gettop(m_pLua);
printf("debug lua: stack size after GetUserdata = %d\n", nSize2);
if (nSize1 != nSize2)
stackDump(m_pLua);
#endif return pRet;
failed:
lua_settop(m_pLua, nSize1);
return NULL;
}
static void stackDump(lua_State *m_pLua) {
int i;
int top = lua_gettop(m_pLua);
for (i = 1; i <= top; i++) {
/* repeat for each level */ int t = lua_type(m_pLua, i);
switch (t) {
case LUA_TSTRING:
/* strings */ printf("`%s'", lua_tostring(m_pLua, i));
break;
case LUA_TBOOLEAN:
/* booleans */ printf(lua_toboolean(m_pLua, i) ? "true" : "false");
break;
case LUA_TNUMBER:
/* numbers */ printf("%g", lua_tonumber(m_pLua, i));
break;
default:
/* other values */ printf("%s", lua_typename(m_pLua, t));
break;
}
printf(" ");
/* put a separator */ }
printf("\n");
/* end the listing */}
bool ScriptVM::LoadFileToBuffer(
const char * filename, unsigned
char *& buff,
int& size,
bool bAssertOnError)
{
IO::Stream* pStream = IO::IOServer::Instance()->CreateReadStream(filename);
if (pStream != NULL && pStream->Open())
{
size = pStream->GetSize();
if (size == 0)
{
std::
string sMsg;
sMsg.append(filename).append("以上文件中无内容!");
assert( sMsg.c_str());
}
buff =
new unsigned
char[size];
pStream->Read(buff, size);
pStream->Close();
IO::IOServer::Instance()->ReleaseStream(pStream);
return true;
}
else {
std::
string sMsg;
sMsg.append("[").append(filename).append("]脚本文件不存在!");
assert( sMsg.c_str());
if (NULL != pStream)
{
IO::IOServer::Instance()->ReleaseStream(pStream);
}
return false;
}
}
//由tolua注册过的类名创建对象
void * ScriptVM::CreateObjectByTypeName(
const char * sTypeName)
{
//处理lua脚本
int nSize = (
int)strlen(sTypeName) + 20;
unsigned
char* buffer =
new unsigned
char[nSize];
sprintf_s((
char*)buffer, nSize, "pMyCreatedObj=%s:new()", sTypeName);
//执行脚本
ExecuteScript((
char*)buffer);
void* ret = GetGlobalUserdata("pMyCreatedObj");
return ret;
}
//获得全局表中常量
double ScriptVM::GetGlobalTableNumber(
const char *sTableName,
const char* key)
{
double ret = 0;
int nSize1 = lua_gettop(m_pLua);
int nSize2 = 0;
#if DEBUG_STACK
//debug
printf("debug lua: stack size before GetGlobalUserdata = %d\n", nSize1);
#endif lua_getglobal(m_pLua, sTableName);
if (!lua_istable(m_pLua, -1))
{
error_msg(
true, "GetGlobalTableNumber: %s isn't a Lua Table.", sTableName);
goto failed;
}
lua_pushstring(m_pLua, key);
lua_gettable(m_pLua, -2);
if (!lua_isnumber(m_pLua, -1))
{
error_msg(
true, "GetGlobalTableNumber: %s isn't a number.", key);
goto failed;
}
ret = lua_tonumber(m_pLua, -1);
lua_settop(m_pLua, nSize1);
#if DEBUG_STACK
//debug
nSize2 = lua_gettop(m_pLua);
printf("debug lua: stack size after GetUserdata = %d\n", nSize2);
if (nSize1 != nSize2)
stackDump(m_pLua);
#endif return ret;
failed:
lua_settop(m_pLua, nSize1);
return 0;
}
void ScriptVM::SetHook(lua_Hook func,
int nMask,
int nCount)
{
if (!m_pLua)
return;
//lua_sethook(m_pLua, func, nMask, nCount);
}
bool ScriptVM::ExistVariable(
const std::vector<
const char *>& modules,
const char * name)
{
int nSize1 = lua_gettop(m_pLua);
if (modules.empty())
//userdata is global
{
lua_getglobal(m_pLua, name);
}
else {
//trace down the modules
std::vector<
const char *>::const_iterator it = modules.begin();
//get the global module name or the actual function name if there is no module
lua_getglobal(m_pLua, *it);
if (!lua_istable(m_pLua, -1))
{
error_msg(
true, "GetUserdata: Invalid table name: %s\n", *it);
goto failed;
}
for (++it; it != modules.end(); ++it)
{
lua_pushstring(m_pLua, *it);
lua_gettable(m_pLua, -2);
if (!lua_istable(m_pLua, -1))
{
error_msg(
true, "GetUserdata: Invalid table name: %s\n", *it);
goto failed;
}
}
//get the data
lua_pushstring(m_pLua, name);
lua_gettable(m_pLua, -2);
}
if (lua_isnil(m_pLua, -1))
{
goto failed;
}
else {
goto success;
}
failed:
lua_settop(m_pLua, nSize1);
return false;
success:
lua_settop(m_pLua, nSize1);
return true;
}
// 替换字符串
void string_replace(std::
string &strBig,
const std::
string &strsrc,
const std::
string &strdst)
{
std::
string::size_type pos = 0;
std::
string::size_type srclen = strsrc.size();
std::
string::size_type dstlen = strdst.size();
while ((pos = strBig.find(strsrc, pos)) != std::
string::npos)
{
strBig.replace(pos, srclen, strdst);
pos += dstlen;
}
}
double ScriptVM::ComputingFormula(
const char* sFormula,
const std::map<std::
string,
double>& kParams)
{
std::
string sRealFormula = sFormula;
if (sRealFormula == "")
{
assert(
false && "公式错误");
return 0.0;
}
std::
string sParamValue = "0";
std::stringstream kStrStream;
// 替换参数
for (std::map<std::
string,
double>::const_iterator it(kParams.begin()); it != kParams.end(); it++)
{
// 得到公式
// kStrStream<<it->second;
// sParamValue = kStrStream.str();
sParamValue = std_string_format(sParamValue, "%f", it->second);
string_replace(sRealFormula, it->first, sParamValue);
/*
// 支持在公式中包含的脚本函数调用可以有字符串参数,避免以当前属性名为字符串的参数被属性值替换 [2/18/2011 shuaiwang]
if (sRealFormula.find('\'') != 0xffffffff)
{
std::string sProParam = std::string("\'").append(it->first).append("\'");
sRealFormula.replace(sProParam, "????");
sRealFormula.replace(it->first, sParamValue);
sProParam = std::string("\"").append(it->first).append("\"");
sRealFormula.replace("????", sProParam);
}
else
{
sRealFormula.replace(it->first, sParamValue);
}
*/
//sRealFormula.Replace(it->first, sParamValue);
}
std::
string sReturn = "return ";
if (sRealFormula.find(sReturn) == std::
string::npos)
{
sRealFormula = sReturn.append(sRealFormula);
}
/*std::stringstream kFunStream;
kFunStream<<"computing_formula_teamfunction = function()\n"
<< sRealFormula << "\n"
<< "end";*/ std::
string sTempFunction = std::
string("computing_formula_teamfunction = function()\n").append(sRealFormula).append("\nend")
/*kFunStream.str()*/;
ExecuteScript(sTempFunction.c_str(),
true);
std::vector<
const char *> modules;
double dValue = 0.0;
if (ExecuteScriptFunc(modules, "computing_formula_teamfunction",
false, ">d", &dValue) ==
false)
{
//_logError2("computing_formula_teamfunction这个问题的来源是:", sFormula << ",请在数据表中修改相应公式!");
}
ExecuteScript("computing_formula_teamfunction = nil",
true);
return dValue;
}
std::
string ScriptVM::GetScriptReturnString(std::
string sScript)
{
std::
string sReturn = "return ";
if (sScript.find(sReturn) == 0xffffffff)
{
sScript = sReturn.append("\"").append(sScript).append("\"");
}
std::
string sTempFunction = std::
string("string_function = function()\n").append(sScript).append("\nend");
ExecuteScript(sTempFunction.c_str(),
true);
std::vector<
const char *> modules;
std::
string sReturnString;
ExecuteScriptFunc(modules, "string_function",
false, ">s", &sReturnString);
ExecuteScript("string_function = nil",
true);
return sReturnString.c_str();
}
void ScriptVM::RegistGlobalFunction(
const char* sFunctionName, lua_CFunction pFunction)
{
lua_register(m_pLua, sFunctionName, pFunction);
}
bool ScriptVM::GetNumber(
const std::vector<
const char *>& modules,
const char * name,
double& dValue)
{
int nSize1 = lua_gettop(m_pLua);
if (modules.empty())
//userdata is global
{
lua_getglobal(m_pLua, name);
}
else {
//trace down the modules
std::vector<
const char *>::const_iterator it = modules.begin();
//get the global module name or the actual function name if there is no module
lua_getglobal(m_pLua, *it);
if (!lua_istable(m_pLua, -1))
{
error_msg(
true, "GetUserdata: Invalid table name: %s\n", *it);
lua_settop(m_pLua, nSize1);
return false;
}
for (++it; it != modules.end(); ++it)
{
lua_pushstring(m_pLua, *it);
lua_gettable(m_pLua, -2);
if (!lua_istable(m_pLua, -1))
{
error_msg(
true, "GetUserdata: Invalid table name: %s\n", *it);
lua_settop(m_pLua, nSize1);
return false;
}
}
//get the data
lua_pushstring(m_pLua, name);
lua_gettable(m_pLua, -2);
}
if (lua_isnumber(m_pLua, -1))
{
dValue = tolua_tonumber(m_pLua, -1, 0);
lua_settop(m_pLua, nSize1);
return true;
}
else {
lua_settop(m_pLua, nSize1);
return false;
}
}
void ScriptVM::DoExecuteFunc(
const char* func,
bool bAllowNonexist,
const ScriptVmArgs::ArgsInput& input, ScriptVmArgs::ArgsOutput& output,
const std::vector<
const char*>* pModuls)
{
//get the actual function
const int nOrgSize = lua_gettop(m_pLua);
int nInputSize = input.Size();
int nOutputSize = output.Size();
if (!pModuls || (pModuls && pModuls->empty()))
//func is global
{
lua_getglobal(m_pLua, func);
if (!lua_isfunction(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid function name: %s\n", func);
goto failed;
}
}
else {
//trace down the modules
std::vector<
const char *>::const_iterator it = pModuls->begin();
//get the global module name or the actual function name if there is no module
lua_getglobal(m_pLua, *it);
if (!lua_istable(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid table name: %s\n", *it);
goto failed;
}
for (++it; it != pModuls->end(); ++it)
{
lua_pushstring(m_pLua, *it);
lua_gettable(m_pLua, -2);
if (!lua_istable(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid table name: %s\n", *it);
goto failed;
}
}
//get the func
lua_pushstring(m_pLua, func);
lua_gettable(m_pLua, -2);
if (!lua_isfunction(m_pLua, -1))
{
if (!bAllowNonexist)
error_msg(
true, "ExecuteScriptFunc: Invalid function name: %s\n", func);
goto failed;
}
}
/* push arguments */ input.Push(*m_pLua);
/* do the call */ if (lua_pcall(m_pLua, nInputSize, nOutputSize, 0) != 0)
/* do the call */ {
report_last_error(m_pLua,
true);
goto failed;
}
/* retrieve results */ output.Pop(*m_pLua);
failed:
//clear the stack
lua_settop(m_pLua, nOrgSize);
}
int ScriptVM::GetConsumeMemoryCount()
{
int nCount = 0;
if (m_pLua)
{
nCount = lua_getgccount(m_pLua);
}
return nCount;
}
void ScriptVM::PrintGlobalVariables()
{
ExecuteScript("for n in pairs(_G) do print(n) end",
true);
}
void ScriptVmArgs::DoPush(lua_State& lua,
const char* pcArg)
{
lua_pushstring(&lua, pcArg);
}
void ScriptVmArgs::DoPush(lua_State& lua,
const bool bArg)
{
lua_pushboolean(&lua, bArg);
}
void ScriptVmArgs::DoPush(lua_State& lua,
const float fArg)
{
lua_pushnumber(&lua, fArg);
}
void ScriptVmArgs::DoPush(lua_State& lua,
const int nArg)
{
lua_pushnumber(&lua, nArg);
}
void ScriptVmArgs::DoPush(lua_State& lua, unsigned uArg)
{
lua_pushinteger(&lua, uArg);
}
void ScriptVmArgs::DoPop(lua_State& lua,
bool& bArg,
int idx)
{
bArg = lua_toboolean(&lua, idx) != 0;
}
void ScriptVmArgs::DoPop(lua_State& lua, std::
string& sArg,
int idx)
{
sArg = lua_tostring(&lua, idx);
}
void ScriptVmArgs::DoPop(lua_State& lua,
float& fArg,
int idx)
{
fArg = (
float)lua_tonumber(&lua, idx);
}
void ScriptVmArgs::DoPop(lua_State& lua,
int& nArg,
int idx)
{
nArg = (
int)lua_tonumber(&lua, idx);
}
void ScriptVmArgs::DoPop(lua_State& lua, unsigned& uArg,
int idx)
{
uArg = lua_tointeger(&lua, idx);
}