a8/a8/luaengine.cc
2022-02-07 15:20:13 +08:00

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