mirror of
https://gitcode.com/JianFeeeee/LuaCangjia_api.git
synced 2026-09-19 16:42:48 +00:00
- C++ 层: callfunction_int/num/bool/void + run_int/num/bool/void - 新增 capture_result()/finish_call() 正确计算 lua_pcall 实际返回值数量, 修复无返回值场景下误读栈残留的问题 - C FFI 层: 11 个新导出函数 + lua_runner 结构体 tresult_* 镜像字段 - 仓颉层: callFunctionInt/Num/Bool, runScriptInt/Num/Bool, resultType() 带严格类型校验(不匹配抛 LUAERR_RESULT_TYPE) - 大整数跨 2^53 保真(字符串路径做不到) - 管道模式语义保留给字符串 API; typed run_* 为独立调用保持栈清洁 - GTest 新增 10 个 typed 测试用例(共 44 个全部通过) - 独立程序验证仓颉层运行时正确性(int/num/bool直通/大整数保真/错误路径)
722 lines
18 KiB
C++
Executable File
722 lines
18 KiB
C++
Executable File
#include "lua_runner.hpp"
|
||
#include <cstring>
|
||
#include <functional>
|
||
|
||
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 = LUAERR_LUA_STATE;
|
||
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 = \";./luapkg/?/init.lua\"") != LUA_OK)//TODO 修改加载库的默认路径
|
||
errno = LUAERR_INIT_FAIL;//加载默认路径*/
|
||
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 = LUAERR_INIT_FAIL;
|
||
}
|
||
this->pkg_cont = 0;
|
||
this->func_cont = 0;
|
||
// typed interop 初始状态
|
||
this->last_result_type = CJT_NIL;
|
||
this->last_result_int = 0;
|
||
this->last_result_num = 0.0;
|
||
this->last_result_bool = 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 = LUAERR_LUA_STATE;
|
||
return false;
|
||
}
|
||
//分为两部分写,防止空指针访问
|
||
if(lua_status(this->L) != LUA_OK)
|
||
{
|
||
errno = LUAERR_LUA_STATE;
|
||
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 = LUAERR_LOAD_FILE;
|
||
return -1;
|
||
}
|
||
if(this->pkg_cont>=MAX_LUA_LIB)
|
||
{
|
||
errno = LUAERR_LIB_OVERFLOW;
|
||
return -1;
|
||
}
|
||
if(luaL_loadfile(this->L,path)!=LUA_OK)
|
||
{
|
||
const char *ret = lua_tostring(this->L, -1);
|
||
this->reslt = ret;//存储返回值
|
||
errno =LUAERR_LOAD_FILE;
|
||
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 = LUAERR_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;
|
||
// 清理预加载函数
|
||
for(int i = 0; i < this->func_cont; i++)
|
||
{
|
||
luaL_unref(this->L, LUA_REGISTRYINDEX, this->funcs[i].ref);
|
||
}
|
||
this->func_cont = 0;
|
||
this->reslt ="nil";
|
||
lua_settop(this->L, 0);//清空栈
|
||
return 0;
|
||
}
|
||
|
||
//TODO 支持更多类型的参数
|
||
int Lua_runner::loadfunction(const char *path,const char *name)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
if(!this->check_file_exists(path))
|
||
{
|
||
errno = LUAERR_LOAD_FILE;
|
||
return -1;
|
||
}
|
||
if(this->func_cont >= MAX_LUA_FUNC)
|
||
{
|
||
errno = LUAERR_FUNC_OVERFLOW;
|
||
return -1;
|
||
}
|
||
// 检查是否已存在同名函数
|
||
for(int i = 0; i < this->func_cont; i++)
|
||
{
|
||
if(strcmp(this->funcs[i].name, name) == 0)
|
||
{
|
||
errno = LUAERR_FUNCTION_NOT_FOUND;
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 1. 加载文件到栈顶(编译成 chunk)
|
||
if(luaL_loadfile(this->L, path) != LUA_OK)
|
||
{
|
||
const char *ret = lua_tostring(this->L, -1);
|
||
this->reslt = ret;
|
||
errno = LUAERR_LOAD_FILE;
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
|
||
// 2. 执行 chunk(顶层代码),期望返回一个函数
|
||
if(lua_pcall(this->L, 0, 1, 0) != LUA_OK)
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
|
||
// 3. 检查栈顶是否为函数
|
||
if(!lua_isfunction(this->L, -1))
|
||
{
|
||
errno = LUAERR_FUNCTION_INVALID;
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
|
||
// 4. 存入 Lua Registry(绝对引用,不受栈变化影响)
|
||
int ref = luaL_ref(this->L, LUA_REGISTRYINDEX);
|
||
|
||
// 5. 记录到 funcs 表
|
||
snprintf(this->funcs[this->func_cont].name, 128, "%s", name);
|
||
this->funcs[this->func_cont].ref = ref;
|
||
this->func_cont++;
|
||
|
||
return 0;
|
||
}
|
||
|
||
int Lua_runner::unloadfunction(const char *name)
|
||
{
|
||
int sig = -1;
|
||
for(int i = 0; i < this->func_cont; i++)
|
||
{
|
||
if(strcmp(this->funcs[i].name, name) == 0)
|
||
{
|
||
sig = i;
|
||
break;
|
||
}
|
||
}
|
||
if(sig == -1)
|
||
{
|
||
errno = LUAERR_FUNCTION_NOT_FOUND;
|
||
return -1;
|
||
}
|
||
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
|
||
// 释放 Registry 引用
|
||
luaL_unref(this->L, LUA_REGISTRYINDEX, this->funcs[sig].ref);
|
||
|
||
// 从 funcs 表中移除
|
||
for(int j = sig + 1; j < this->func_cont; j++)
|
||
{
|
||
this->funcs[j - 1] = this->funcs[j];
|
||
}
|
||
this->func_cont--;
|
||
|
||
return 0;
|
||
}
|
||
|
||
// ============ typed interop 内部辅助 ============
|
||
|
||
// 读取 Lua 栈顶值,记录类型到 last_result_*,并把字符串形式同步到 reslt。
|
||
// 注意:不弹出栈顶(由调用方决定是否 pop)。
|
||
// 计算 lua_pcall 的实际返回值数量并记录结果。
|
||
// pre_top: pcall 前的栈顶(含函数与参数);nargs: 传入参数数。
|
||
// pcall 后栈顶 = pre_top - nargs - 1(函数) + nres,故 nres = post_top - pre_top + nargs + 1
|
||
int Lua_runner::finish_call(int pre_top, int nargs, bool pop_results)
|
||
{
|
||
int nres = lua_gettop(this->L) - pre_top + nargs + 1;
|
||
if(nres <= 0)
|
||
{
|
||
// 无返回值:显式置 NIL,不读栈(避免读到上一次调用残留)
|
||
this->last_result_type = CJT_NIL;
|
||
this->reslt = "nil";
|
||
this->last_result_int = 0;
|
||
this->last_result_num = 0.0;
|
||
this->last_result_bool = 0;
|
||
return nres;
|
||
}
|
||
capture_result();
|
||
if(pop_results)
|
||
{
|
||
// 弹出全部返回值(capture_result 不弹栈)
|
||
for(int i = 0; i < nres; i++)
|
||
lua_pop(this->L, 1);
|
||
}
|
||
return nres;
|
||
}
|
||
|
||
void Lua_runner::capture_result()
|
||
{
|
||
int top = lua_gettop(this->L);
|
||
if(top == 0)
|
||
{
|
||
// 栈为空:没有返回值
|
||
this->last_result_type = CJT_NIL;
|
||
this->reslt = "nil";
|
||
this->last_result_int = 0;
|
||
this->last_result_num = 0.0;
|
||
this->last_result_bool = 0;
|
||
return;
|
||
}
|
||
int t = lua_type(this->L, -1);
|
||
switch (t)
|
||
{
|
||
case LUA_TBOOLEAN:
|
||
this->last_result_type = CJT_BOOL;
|
||
this->last_result_bool = lua_toboolean(this->L, -1) ? 1 : 0;
|
||
this->last_result_int = this->last_result_bool;
|
||
this->last_result_num = this->last_result_bool;
|
||
this->reslt = this->last_result_bool ? "true" : "false";
|
||
break;
|
||
case LUA_TNUMBER:
|
||
{
|
||
// lua_isinteger 区分整型和浮点型
|
||
if (lua_isinteger(this->L, -1))
|
||
{
|
||
this->last_result_type = CJT_INT;
|
||
this->last_result_int = (long long)lua_tointeger(this->L, -1);
|
||
this->last_result_num = (double)this->last_result_int;
|
||
this->last_result_bool = this->last_result_int != 0;
|
||
}
|
||
else
|
||
{
|
||
this->last_result_type = CJT_NUM;
|
||
this->last_result_num = lua_tonumber(this->L, -1);
|
||
this->last_result_int = (long long)this->last_result_num;
|
||
this->last_result_bool = this->last_result_num != 0.0;
|
||
}
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
break;
|
||
}
|
||
case LUA_TSTRING:
|
||
this->last_result_type = CJT_STR;
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
this->last_result_int = 0;
|
||
this->last_result_num = 0.0;
|
||
this->last_result_bool = false;
|
||
break;
|
||
case LUA_TNIL:
|
||
default:
|
||
// nil 及 table/function 等复杂类型统一按 CJT_NIL 处理
|
||
this->last_result_type = CJT_NIL;
|
||
this->reslt = "nil";
|
||
this->last_result_int = 0;
|
||
this->last_result_num = 0.0;
|
||
this->last_result_bool = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
int Lua_runner::callfunction(const char *name,const char *arg)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
|
||
// 在 funcs 表中查找(预加载函数表,独立于管道栈 pkgs[])
|
||
int sig = -1;
|
||
for(int i = 0; i < this->func_cont; i++)
|
||
{
|
||
if(strcmp(this->funcs[i].name, name) == 0)
|
||
{
|
||
sig = i;
|
||
break;
|
||
}
|
||
}
|
||
if(sig == -1)
|
||
{
|
||
errno = LUAERR_FUNCTION_NOT_FOUND;
|
||
return -1;
|
||
}
|
||
|
||
// 从 Lua Registry 中取出函数(绝对引用,不受栈变化影响)
|
||
lua_rawgeti(this->L, LUA_REGISTRYINDEX, this->funcs[sig].ref);
|
||
|
||
// 如果有参数,压入参数
|
||
if(arg != NULL)
|
||
{
|
||
lua_pushlstring(this->L, arg, strlen(arg));
|
||
}
|
||
|
||
int argcount = (arg != NULL) ? 1 : 0;
|
||
int pre_top = lua_gettop(this->L);
|
||
|
||
if(lua_pcall(this->L, argcount, LUA_MULTRET, 0) == LUA_OK)
|
||
{
|
||
finish_call(pre_top, argcount, true);//记录结果并弹出(预加载函数不参与管道)
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// typed 变体共用骨架:查函数→压参数→pcall→finish_call
|
||
static int callfunc_impl(Lua_runner *r, lua_State *L, const ld_func *funcs,
|
||
int func_cont, const char *name,
|
||
std::function<void(lua_State *)> push_args, int nargs)
|
||
{
|
||
int sig = -1;
|
||
for(int i = 0; i < func_cont; i++)
|
||
{
|
||
if(strcmp(funcs[i].name, name) == 0)
|
||
{
|
||
sig = i;
|
||
break;
|
||
}
|
||
}
|
||
if(sig == -1)
|
||
{
|
||
errno = LUAERR_FUNCTION_NOT_FOUND;
|
||
return -1;
|
||
}
|
||
lua_rawgeti(L, LUA_REGISTRYINDEX, funcs[sig].ref);
|
||
if(nargs > 0)
|
||
push_args(L);
|
||
int pre_top = lua_gettop(L);
|
||
if(lua_pcall(L, nargs, LUA_MULTRET, 0) != LUA_OK)
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
r->reslt = lua_tostring(L, -1);
|
||
lua_pop(L, 1);
|
||
return -1;
|
||
}
|
||
r->finish_call(pre_top, nargs, true);//预加载函数不参与管道,弹出结果
|
||
return 0;
|
||
}
|
||
|
||
int Lua_runner::callfunction_int(const char *name, long long val)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
return callfunc_impl(this, this->L, this->funcs, this->func_cont, name,
|
||
[val](lua_State *LL) { lua_pushinteger(LL, (lua_Integer)val); }, 1);
|
||
}
|
||
|
||
int Lua_runner::callfunction_num(const char *name, double val)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
return callfunc_impl(this, this->L, this->funcs, this->func_cont, name,
|
||
[val](lua_State *LL) { lua_pushnumber(LL, (lua_Number)val); }, 1);
|
||
}
|
||
|
||
int Lua_runner::callfunction_bool(const char *name, int val)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
return callfunc_impl(this, this->L, this->funcs, this->func_cont, name,
|
||
[val](lua_State *LL) { lua_pushboolean(LL, val ? 1 : 0); }, 1);
|
||
}
|
||
|
||
int Lua_runner::callfunction_void(const char *name)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
return callfunc_impl(this, this->L, this->funcs, this->func_cont, name,
|
||
[](lua_State *) {}, 0);
|
||
}
|
||
|
||
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 = LUAERR_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 = LUAERR_LUA_STACK;
|
||
return -1;
|
||
}//检查参数数量
|
||
int pre_top = top;
|
||
if(lua_pcall(this->L,argcount,LUA_MULTRET,0)== LUA_OK)
|
||
{
|
||
//管道模式:结果留在栈上供下一个节点使用,仅记录类型
|
||
finish_call(pre_top, argcount, false);
|
||
this->pkg_cont--;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
this->reslt = lua_tostring(this->L,-1);
|
||
this->pkg_cont--;
|
||
lua_pop(L,1);//错误出栈
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
int Lua_runner::run_int(const char *path, long long val)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
if(path != NULL)
|
||
{
|
||
if(this->load_lib(path, path) != 0)
|
||
return -1;
|
||
}
|
||
lua_pushinteger(this->L, (lua_Integer)val);
|
||
if(this->pkg_cont <= 0)
|
||
{
|
||
errno = LUAERR_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 = LUAERR_LUA_STACK;
|
||
return -1;
|
||
}
|
||
int pre_top = top;
|
||
if(lua_pcall(this->L, argcount, LUA_MULTRET, 0) == LUA_OK)
|
||
{
|
||
finish_call(pre_top, argcount, true);//独立调用,弹出结果
|
||
this->pkg_cont--;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
this->pkg_cont--;
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
int Lua_runner::run_num(const char *path, double val)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
if(path != NULL)
|
||
{
|
||
if(this->load_lib(path, path) != 0)
|
||
return -1;
|
||
}
|
||
lua_pushnumber(this->L, (lua_Number)val);
|
||
if(this->pkg_cont <= 0)
|
||
{
|
||
errno = LUAERR_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 = LUAERR_LUA_STACK;
|
||
return -1;
|
||
}
|
||
int pre_top = top;
|
||
if(lua_pcall(this->L, argcount, LUA_MULTRET, 0) == LUA_OK)
|
||
{
|
||
finish_call(pre_top, argcount, true);
|
||
this->pkg_cont--;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
this->pkg_cont--;
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
int Lua_runner::run_bool(const char *path, int val)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
if(path != NULL)
|
||
{
|
||
if(this->load_lib(path, path) != 0)
|
||
return -1;
|
||
}
|
||
lua_pushboolean(this->L, val ? 1 : 0);
|
||
if(this->pkg_cont <= 0)
|
||
{
|
||
errno = LUAERR_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 = LUAERR_LUA_STACK;
|
||
return -1;
|
||
}
|
||
int pre_top = top;
|
||
if(lua_pcall(this->L, argcount, LUA_MULTRET, 0) == LUA_OK)
|
||
{
|
||
finish_call(pre_top, argcount, true);
|
||
this->pkg_cont--;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
this->pkg_cont--;
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
int Lua_runner::run_void(const char *path)
|
||
{
|
||
if(!this->check_luastatue())
|
||
return -1;
|
||
if(path != NULL)
|
||
{
|
||
if(this->load_lib(path, path) != 0)
|
||
return -1;
|
||
}
|
||
if(this->pkg_cont <= 0)
|
||
{
|
||
errno = LUAERR_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 = LUAERR_LUA_STACK;
|
||
return -1;
|
||
}
|
||
if(lua_pcall(this->L, argcount, LUA_MULTRET, 0) == LUA_OK)
|
||
{
|
||
finish_call(top, argcount, true);
|
||
this->pkg_cont--;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
errno = LUAERR_SCRIPT_ERROR;
|
||
this->reslt = lua_tostring(this->L, -1);
|
||
this->pkg_cont--;
|
||
lua_pop(this->L, 1);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
int Lua_runner::dostring(const char *target)
|
||
{
|
||
if(target == NULL)
|
||
{
|
||
errno = LUAERR_CALLBACK;
|
||
return -1;
|
||
}
|
||
if(luaL_dostring(this->L,target) != LUA_OK)
|
||
{
|
||
errno = LUAERR_CALLBACK;
|
||
this->reslt = lua_tostring(this->L,-1);
|
||
lua_pop(L,1);//错误出栈
|
||
return -1;
|
||
}
|
||
if(lua_gettop(this->L) == 0) {
|
||
errno = LUAERR_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 = LUAERR_SCRIPT_BAD_RET;
|
||
lua_pop(L,1);
|
||
return -1;
|
||
}
|
||
}
|
||
//TODO 实现函数调用 achieve func call via file
|
||
/*
|
||
int Lua_runner::callfunction()
|
||
{
|
||
return 0;
|
||
}
|
||
*/
|