179 lines
5.5 KiB
C++
179 lines
5.5 KiB
C++
#include <a8/a8.h>
|
|
#include <a8/luaengine.h>
|
|
|
|
#ifdef A8_USE_LUA
|
|
|
|
extern "C"
|
|
{
|
|
#include <lua.h>
|
|
#include <lauxlib.h>
|
|
#include <lualib.h>
|
|
};
|
|
|
|
namespace a8
|
|
{
|
|
LuaEngine::LuaEngine()
|
|
{
|
|
lua_state_ = luaL_newstate();
|
|
if (!lua_state_) {
|
|
abort();
|
|
}
|
|
luaL_openlibs(lua_state_);
|
|
}
|
|
|
|
LuaEngine::~LuaEngine()
|
|
{
|
|
if (lua_state_) {
|
|
lua_close(lua_state_);
|
|
lua_state_ = nullptr;
|
|
}
|
|
}
|
|
|
|
void LuaEngine::Init(const std::string& lua_path)
|
|
{
|
|
lua_path_ = lua_path;
|
|
}
|
|
|
|
void LuaEngine::UnInit()
|
|
{
|
|
|
|
}
|
|
|
|
bool LuaEngine::LoadModule(const std::string& module_name)
|
|
{
|
|
std::string real_filename = lua_path_ + module_name;
|
|
a8::ReplaceString(real_filename, ".", "/");
|
|
real_filename = real_filename + ".lua";
|
|
int ret = luaL_loadfile(lua_state_, real_filename.c_str())
|
|
|| lua_pcall(lua_state_, 0, 1, 0);
|
|
if (ret != 0){
|
|
std::string errormsg = lua_tostring(lua_state_, -1);
|
|
lua_pop(lua_state_, 1);
|
|
OnScriptError(errormsg);
|
|
return false;
|
|
}
|
|
std::string module_varname = "module_" + module_name;
|
|
a8::ReplaceString(module_varname, ".", "_");
|
|
if (lua_istable(lua_state_, -1)) {
|
|
lua_setglobal(lua_state_, module_varname.c_str());
|
|
return true;
|
|
} else {
|
|
OnScriptError("return value is not table");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool LuaEngine::LoadString(const std::string& str)
|
|
{
|
|
int ret = luaL_loadstring(lua_state_, str.c_str())
|
|
|| lua_pcall(lua_state_, 0, 0, 0);
|
|
if (ret != 0){
|
|
std::string errormsg = lua_tostring(lua_state_, -1);
|
|
lua_pop(lua_state_, 1);
|
|
OnScriptError(errormsg);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::tuple<bool, a8::XValue> LuaEngine::CallGlobalFunc(const char* func_name,
|
|
std::initializer_list<a8::XValue> args)
|
|
{
|
|
a8::XValue result;
|
|
bool ret = CallLuaFunc(NULL, func_name, args, result);
|
|
return std::make_tuple(ret, result);
|
|
}
|
|
|
|
std::tuple<bool, a8::XValue> LuaEngine::CallModuleFunc(const char* module_name,
|
|
const char* func_name,
|
|
std::initializer_list<a8::XValue> args)
|
|
{
|
|
a8::XValue result;
|
|
bool ret = CallLuaFunc(module_name, func_name, args, result);
|
|
return std::make_tuple(ret, result);
|
|
}
|
|
|
|
bool LuaEngine::CallLuaFunc(const char* module_name,
|
|
const char* func_name,
|
|
std::initializer_list<a8::XValue>& args,
|
|
a8::XValue& result)
|
|
{
|
|
if (module_name) { //call module function
|
|
std::string module_varname = std::string("module_") + module_name;
|
|
a8::ReplaceString(module_varname, ".", "_");
|
|
lua_getglobal(lua_state_, module_varname.c_str());
|
|
if (!lua_istable(lua_state_, -1)) {
|
|
OnScriptError(a8::Format("%s is not table", {module_name}));
|
|
lua_pop(lua_state_, 1);
|
|
return false;
|
|
}
|
|
lua_getfield(lua_state_, -1, func_name);
|
|
if (!lua_isfunction(lua_state_, -1)) {
|
|
OnScriptError(a8::Format("%s function not found", {func_name}));
|
|
lua_pop(lua_state_, 2);
|
|
return false;
|
|
}
|
|
} else { // call global function
|
|
lua_getglobal(lua_state_, func_name);
|
|
if (!lua_isfunction(lua_state_, -1)) {
|
|
OnScriptError(a8::Format("%s function not found", {func_name}));
|
|
lua_pop(lua_state_, 1);
|
|
return false;
|
|
}
|
|
}
|
|
for (auto &arg : args) {
|
|
switch(arg.Type()){
|
|
case XVT_INT:
|
|
lua_pushnumber(lua_state_, arg.GetInt());
|
|
break;
|
|
case XVT_UINT:
|
|
lua_pushnumber(lua_state_, arg.GetUInt());
|
|
break;
|
|
case XVT_FLOAT:
|
|
lua_pushnumber(lua_state_, arg.GetDouble());
|
|
break;
|
|
case XVT_INT64:
|
|
lua_pushstring(lua_state_, arg.GetString().c_str());
|
|
break;
|
|
case XVT_UINT64:
|
|
lua_pushstring(lua_state_, arg.GetString().c_str());
|
|
break;
|
|
case XVT_STRING:
|
|
lua_pushstring(lua_state_, arg.GetString().c_str());
|
|
break;
|
|
default:
|
|
abort();
|
|
break;
|
|
}
|
|
}
|
|
if (lua_pcall(lua_state_, args.size(), 1, 0) == 0){
|
|
switch(lua_type(lua_state_, -1)){
|
|
case LUA_TBOOLEAN:
|
|
result.Set(lua_toboolean(lua_state_, -1) ? 1 : 0);
|
|
break;
|
|
case LUA_TNUMBER:
|
|
result.Set(lua_tonumber(lua_state_, -1));
|
|
break;
|
|
case LUA_TSTRING:
|
|
result.Set(lua_tostring(lua_state_, -1));
|
|
break;
|
|
}
|
|
lua_pop(lua_state_, module_name ? 2 : 1);
|
|
return true;
|
|
} else {
|
|
std::string errmsg(lua_tostring(lua_state_, -1));
|
|
lua_pop(lua_state_, module_name ? 2 : 1);
|
|
OnScriptError(errmsg);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void LuaEngine::OnScriptError(const std::string& errormsg)
|
|
{
|
|
last_error_msg_ = errormsg;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|