Files
LuaCangjia_api/lib/lua_runner.cpp
2026-03-22 10:01:23 +08:00

216 lines
5.3 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 argcount = lua_gettop(this->L) - this->pkgs[this->pkg_cont-1].ref;//获取入参数量
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;
}
*/