mirror of
https://gitcode.com/JianFeeeee/LuaCangjia_api.git
synced 2026-09-19 16:42:48 +00:00
250 lines
6.0 KiB
C++
Executable File
250 lines
6.0 KiB
C++
Executable File
#include "lua_runner.hpp"
|
||
#include <cstring>
|
||
|
||
extern "C"
|
||
{
|
||
#include <errno.h>
|
||
#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;i<this->pkg_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;j<this->pkg_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 ;i<this->pkg_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;
|
||
}
|
||
}
|
||
|
||
int Lua_runner::dostring(const char *target)
|
||
{
|
||
if(target == NULL)
|
||
{
|
||
errno = NAPI_ERROR_FUNCS;
|
||
return -1;
|
||
}
|
||
if(luaL_dostring(this->L,target) != LUA_OK)
|
||
{
|
||
errno = NAPI_ERROR_FUNCS;
|
||
this->reslt = lua_tostring(this->L,-1);
|
||
lua_pop(L,1);//错误出栈
|
||
return -1;
|
||
}
|
||
if(lua_gettop(this->L) == 0) {
|
||
errno = NAPI_SCRIPT_BAD_RET;
|
||
this->reslt = "";
|
||
return -1;
|
||
}
|
||
if(lua_isstring(this->L,-1)){
|
||
this->reslt = lua_tostring(this->L,-1);
|
||
lua_pop(L,1);
|
||
return 0;
|
||
}
|
||
else{
|
||
errno = NAPI_SCRIPT_BAD_RET;
|
||
lua_pop(L,1);
|
||
return -1;
|
||
}
|
||
}
|
||
//TODO 实现函数调用 achieve func call via file
|
||
/*
|
||
int Lua_runner::callfunction()
|
||
{
|
||
return 0;
|
||
}
|
||
*/
|