C++调用LuaJit的Demo
头文件#pragma once
extern "C"
{
#include <luajit/src/lua.h>
#include <luajit/src/lualib.h>
#include <luajit/src/lauxlib.h>
#include <luajit/src/luajit.h>
}
class ScriptVM
{
public:
ScriptVM();
~ScriptVM();
bool Init();
void Destroy();
void ExecuteScriptFile(const char* sScriptName, bool bForceReload = false, bool bAssertOnError = true);
//void ExecuteScript(const char* sScript, bool bAssertOnError = true);
protected:
bool LoadFileToBuffer(const std::string& path, std::vector<uint8_t>& buffer);
private:
lua_State* m_pLua;
};
源文件
#include "pch.h"
#include "script_vm.h"
static int wrap_exceptions(lua_State* L, lua_CFunction f)
{
try
{
return f(L);// Call wrapped function and return result.
}
catch (const char* s)
{
// Catch and convert exceptions.
lua_pushstring(L, s);
}
catch (std::exception& e)
{
lua_pushstring(L, e.what());
}
catch (...)
{
lua_pushliteral(L, "caught (...)");
}
return lua_error(L);// Rethrow as a Lua error.
}
static void error_msg(bool bUseAssert, const char* pacFmt, ...)
{
//#if defined(_DEBUG)
char acTemp;
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()
{
}
ScriptVM::~ScriptVM()
{
}
int PrintStringList(lua_State* pLuaState)
{
luaJIT_setmode(pLuaState, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);
// Get the number of strings
int iStringCount = lua_gettop(pLuaState);
// Loop through each string and print it, followed by a newline
for (int iCurrStringIndex = 1; iCurrStringIndex <= iStringCount; ++iCurrStringIndex)
{
// First make sure that the current parameter on the stack is a string
if (!lua_isstring(pLuaState, 1))
{
// If not, print an error
lua_error(pLuaState);
}
else
{
// Otherwise, print a tab, the string, and finally a newline
printf("\t");
printf(lua_tostring(pLuaState, iCurrStringIndex));
printf("\n");
}
}
// Return zero, as this function does not return any results
return 0;
}
bool ScriptVM::Init()
{
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, "PrintStringList", PrintStringList);
//lua_register(m_pLua, "dofile", OverrideDofile);
// 添加 LuaJIT 的支持
lua_pushlightuserdata(m_pLua, (void*)wrap_exceptions);
luaJIT_setmode(m_pLua, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_ON);
return true;
}
void ScriptVM::Destroy()
{
lua_close(m_pLua);
}
bool ScriptVM::LoadFileToBuffer(const std::string& path, std::vector<uint8_t>& buffer)
{
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.is_open())
return false;
std::streamsize size = file.tellg();
if (size <= 0)
return false;
buffer.resize(static_cast<size_t>(size));
file.seekg(0, std::ios::beg);
if (!file.read(reinterpret_cast<char*>(buffer.data()), size))
return false;
return true;
}
void ScriptVM::ExecuteScriptFile(const char* sScriptName, bool bForceReload /* = false*/, bool bAssertOnError /*= true*/)
{
// 添加 LuaJIT 的支持
luaJIT_setmode(m_pLua, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);
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 == '/' || sChunkName == '.')
sChunkName = '_';
}
//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
std::vector<uint8_t> Buffer;
if (LoadFileToBuffer(sScriptName, Buffer))
{
luaL_loadbuffer(m_pLua, (char*)Buffer.data(), Buffer.size(), sScriptName);
// 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)
// {
// // 添加 LuaJIT 的支持
// luaJIT_setmode(m_pLua, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);
//
// 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);
// }
// }
//
// bool ScriptVM::ExecuteScriptFunc(const std::vector<const char*>& modules, const char* func, bool bAllowNonexist, const char* sig, ...)
// {
// // 添加 LuaJIT 的支持
// luaJIT_setmode(m_pLua, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);
//
// 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;
// }
页:
[1]