#include "lua_runner.hpp" #include extern "C" { #include #include "errors.h" } Lua_runner::Lua_runner(const char *path) { this->L =NULL; this->L = luaL_newstate(); errno = 0;//清除老错误信息 if(this->L == NULL){ errno = NAPI_LUA_STATE_ERROR; return ; } luaL_openlibs(this->L);//创建lua状态机,打开标准库 const char* save_stdlib_code = "local std = {} " "for k, v in pairs(_G) do std[k] = true end " "_G.__STD_LIBS = std"; // 将列表存到全局变量 __STD_LIBS 中 luaL_dostring(this->L, save_stdlib_code); /*if(luaL_dostring(this->L, "package.path = \";/data/storage/el2/luapkg/?/init.lua\"") != LUA_OK)//TODO 修改加载库的默认路径指向沙盒内路径 errno = NAPI_LUA_INITFAIL;//加载默认路径*/ if(path !=NULL) { char buf[1024]; snprintf(buf, sizeof(buf), "package.path = package.path .. \";%s\"", path); if(luaL_dostring(this->L,buf) != LUA_OK)//加载用户路径 errno = NAPI_LUA_INITFAIL; } this->pkg_cont = 0; } Lua_runner::~Lua_runner() { lua_close(this->L); } bool Lua_runner::check_file_exists(const char *path) { FILE* file = fopen(path, "r"); if (file) { fclose(file); return true; } return false; } bool Lua_runner::check_luastatue() { /*检查lua状态机状况*/ if(this->L == NULL) { errno = NAPI_LUA_STATE_ERROR; return false; } //分为两部分写,防止空指针访问 if(lua_status(this->L) != LUA_OK) { errno = NAPI_LUA_STATE_ERROR; return false; } return true; } lua_State *Lua_runner::get_lua_State() { return this->L; } int Lua_runner::load_lib(const char *path,const char *name) { //如果引入哈希表会导致删除包时的多次哈希查询,污染缓存。同时性能仅与数组实现相当 if(!this->check_luastatue()) { return -1; } if(!this->check_file_exists(path)) { errno = NAPI_LOAD_FILE_ERROR; return -1; } if(this->pkg_cont>=MAX_LUA_LIB) { errno = NAPI_LUALIB_LOAD_OVER_STACK; return -1; } if(luaL_loadfile(this->L,path)!=LUA_OK) { const char *ret = lua_tostring(this->L, -1); this->reslt = ret;//存储返回值 errno =NAPI_LOAD_FILE_ERROR; lua_pop(this->L,1); return -1; } this->pkgs[this->pkg_cont].ref = lua_gettop(this->L)+1; snprintf(pkgs[pkg_cont].name,128,"%s",name); this->pkg_cont++; return 0; } int Lua_runner::unload_lib(const char *name) { int sig = -1; for(int i=0;ipkg_cont;i++) { if(strcmp(this->pkgs[i].name,name) == 0) { sig = i; break;//查找指定的库,查到则将标志位置为库的位置 } } if(sig == -1) { errno = NAPI_UNLOADLIB_FAIL; return -1;//没有查到返回异常(尝试卸载未加载的库) } /*检查lua状态*/ if(!this->check_luastatue()) { return -1; } lua_remove(this->L,this->pkgs[sig].ref); for(int j = sig+1;jpkg_cont;j++) { this->pkgs[j-1] = this->pkgs[j];//保持数据结构 this->pkgs[j-1].ref--;//虚拟栈位置同步变化 } this->pkg_cont--; return 1; } int Lua_runner::clean()//进行新一轮调用前一定要先clean清除上个脚本执行的痕迹 { if(!this->check_luastatue()) { return -1; } const char* clean_globals_code = "if _G.__STD_LIBS then " " local std = _G.__STD_LIBS " " for k, v in pairs(_G) do " " if not std[k] then _G[k] = nil end " " end " "end"; luaL_dostring(this->L, clean_globals_code);//清空全局变量 luaL_dostring(this->L, "package.loaded = {}");//清空当前引用的包 for(int i = 0 ;ipkg_cont;i++) { lua_remove(this->L,this->pkgs[i].ref); } this->pkg_cont = 0; this->reslt ="nil"; lua_settop(this->L, 0);//清空栈 return 0; } //TODO 支持更多类型的参数 int Lua_runner::run(const char *path,const char *arg) { if(!this->check_luastatue())//检查lua状态机状态 return -1; if(path != NULL)//加载脚本到栈 { if(this->load_lib(path,path) != 0) return -1; } if(arg != NULL)//压参数入栈 { lua_pushlstring(this->L,arg,strlen(arg)); } if(this->pkg_cont <= 0)//检查是否有可调用chunk { errno = NAPI_NOCHUNK_FOUND; return -1; } int func_index = this->pkgs[this->pkg_cont-1].ref - 1; int top = lua_gettop(this->L); int argcount = top - func_index;//获取入参数量 if(argcount<0) { errno = NAPI_LUA_STACK_ERROR; return -1; }//检查参数数量 if(lua_pcall(this->L,argcount,LUA_MULTRET,0)== LUA_OK) { if(lua_isstring(this->L,-1)) this->reslt = lua_tostring(this->L,-1); this->pkg_cont--; return 0; } else { errno = NAPI_SCRIPT_ERROR; this->reslt = lua_tostring(this->L,-1); this->pkg_cont--; lua_pop(L,1);//错误出栈 return -1; } } //TODO 实现函数调用 achieve func call via file /* int Lua_runner::callfunction() { return 0; } */