mirror of
https://gitcode.com/JianFeeeee/LuaCangjia_api.git
synced 2026-09-20 08:58:13 +00:00
feat: typed interop 原始类型直通映射 (Int64/Float64/Bool)
- 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直通/大整数保真/错误路径)
This commit is contained in:
@ -12,13 +12,13 @@ bool check_luastatue(lua_State *L)
|
||||
/*检查lua状态机状况*/
|
||||
if(L == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STACK_ERROR;
|
||||
errno = LUAERR_LUA_STACK;
|
||||
return false;
|
||||
}
|
||||
//分为两部分写,防止空指针访问
|
||||
if(lua_status(L) != LUA_OK)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -26,6 +26,15 @@ bool check_luastatue(lua_State *L)
|
||||
|
||||
int get_errno(void) { return errno; }//获取错误码
|
||||
|
||||
// 同步 typed 结果:把 Lua_runner 的 last_result_* 拷贝到外层 lua_runner 结构体
|
||||
static void sync_typed_result(lua_runner *self, Lua_runner *runner)
|
||||
{
|
||||
self->tresult_type = runner->last_result_type;
|
||||
self->tresult_int = runner->last_result_int;
|
||||
self->tresult_num = runner->last_result_num;
|
||||
self->tresult_bool = runner->last_result_bool;
|
||||
}
|
||||
|
||||
/// @brief 加载lua文件到lua虚拟栈
|
||||
/// @param self 使用init_lua_runner初始化的lua_runner结构体指针
|
||||
/// @param path 需要加载的脚本的位置
|
||||
@ -37,7 +46,7 @@ int load_lib(void *selfd,const char *path,const char *name)
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->load_lib(path,name)==-1)
|
||||
@ -54,7 +63,7 @@ int unload_lib(void *selfd,const char *name)
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->unload_lib(name)==-1)
|
||||
@ -64,7 +73,7 @@ int unload_lib(void *selfd,const char *name)
|
||||
|
||||
/// @brief 运行脚本(可指定入参)
|
||||
/// @param self 使用init_lua_runner初始化的lua_runner结构体指针
|
||||
/// @param path 脚本的沙盒内路径
|
||||
/// @param path 脚本路径
|
||||
/// @param arg 脚本的入参
|
||||
/// @return 0代表正常结束,-1表示异常退出
|
||||
int run(void *selfd,const char *path,const char *arg)
|
||||
@ -74,7 +83,7 @@ int run(void *selfd,const char *path,const char *arg)
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->run(path,arg)==-1)
|
||||
@ -97,7 +106,7 @@ int loadfunction(void *selfd,const char *path,const char *name)
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->loadfunction(path,name)==-1)
|
||||
@ -115,7 +124,7 @@ int unloadfunction(void *selfd,const char *name)
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->unloadfunction(name)==-1)
|
||||
@ -134,7 +143,7 @@ int callfunction(void *selfd,const char *name,const char *arg)
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->callfunction(name,arg)==-1){
|
||||
@ -142,9 +151,162 @@ int callfunction(void *selfd,const char *name,const char *arg)
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------typed interop(v0.2.2)------------------------*/
|
||||
|
||||
int callfunction_int(void *selfd,const char *name,long long val)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->callfunction_int(name,val)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int callfunction_num(void *selfd,const char *name,double val)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->callfunction_num(name,val)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int callfunction_bool(void *selfd,const char *name,int val)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->callfunction_bool(name,val)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int callfunction_void(void *selfd,const char *name)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->callfunction_void(name)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_int(void *selfd,const char *path,long long val)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->run_int(path,val)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_num(void *selfd,const char *path,double val)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->run_num(path,val)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_bool(void *selfd,const char *path,int val)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->run_bool(path,val)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_void(void *selfd,const char *path)
|
||||
{
|
||||
lua_runner* self = (lua_runner*)selfd;
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->run_void(path)==-1){
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
return -1;
|
||||
}
|
||||
snprintf(self->result,MAX_RESULT,"%s",runner->reslt.c_str());
|
||||
sync_typed_result(self, runner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int result_type(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_type;}
|
||||
long long result_int(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_int;}
|
||||
double result_num(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_num;}
|
||||
int result_bool(void *selfd){lua_runner*self =(lua_runner*)selfd;return self->tresult_bool;}
|
||||
/*-------------typed interop------------------------*/
|
||||
|
||||
/// @brief 执行单句lua语句
|
||||
/// @param selfd init_lua_runner返回的void指针
|
||||
/// @param target 执行语句(字符串类型)
|
||||
@ -155,7 +317,7 @@ int dostring(void *selfd,const char *target){
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->dostring(target)==-1){
|
||||
@ -175,7 +337,7 @@ int cleanup(void *selfd)
|
||||
Lua_runner *runner = (Lua_runner*)self->lua_obj;//还原对象
|
||||
if(runner == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
if(runner->clean()==-1)
|
||||
@ -221,7 +383,7 @@ static int l_tty_read(lua_State *L)
|
||||
fclose(fp);
|
||||
if(remove(fname) != 0)
|
||||
{
|
||||
errno = NAPI_RESET_INPUT_FILE_ERROR;
|
||||
errno = LUAERR_RESET_INPUT_FILE;
|
||||
return luaL_error(L, "fail to reset input file: %s", fname);
|
||||
}
|
||||
lua_pushlstring(L, tmp, sz);
|
||||
@ -310,7 +472,7 @@ static void push_tty_file(lua_State *L, int isout, const luaL_Reg *fake_tty_meta
|
||||
int redirecct_path(lua_State *L)
|
||||
{
|
||||
if(!check_luastatue(L)){
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return -1;
|
||||
}
|
||||
iopath *p = (iopath*)lua_getextraspace(L);
|
||||
@ -362,13 +524,18 @@ void *init_lua_runner(const char *pathio,const char *pkgpath,int(*input)(),int(*
|
||||
{
|
||||
//分配内存
|
||||
lua_runner *self = (lua_runner*)malloc(sizeof(lua_runner));
|
||||
// typed interop 字段初始化
|
||||
self->tresult_type = CJT_NIL;
|
||||
self->tresult_int = 0;
|
||||
self->tresult_num = 0.0;
|
||||
self->tresult_bool = 0;
|
||||
//创建对象
|
||||
self->lua_obj = (void*)new Lua_runner(pkgpath);
|
||||
if(errno != 0)
|
||||
return NULL;
|
||||
if(self->lua_obj == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_CLASS_LOST;
|
||||
errno = LUAERR_CLASS_LOST;
|
||||
return NULL;
|
||||
}
|
||||
//提取对象
|
||||
@ -377,7 +544,7 @@ void *init_lua_runner(const char *pathio,const char *pkgpath,int(*input)(),int(*
|
||||
lua_State *L = runner->get_lua_State();
|
||||
|
||||
if(!check_luastatue(L)){
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return NULL;
|
||||
}
|
||||
iopath *io_path = (iopath*)lua_getextraspace(L);
|
||||
@ -388,7 +555,7 @@ void *init_lua_runner(const char *pathio,const char *pkgpath,int(*input)(),int(*
|
||||
}
|
||||
|
||||
if(io_path == NULL){
|
||||
errno = NAPI_ERROR_FUNCS;
|
||||
errno = LUAERR_CALLBACK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -399,7 +566,7 @@ void *init_lua_runner(const char *pathio,const char *pkgpath,int(*input)(),int(*
|
||||
strcpy(io_path->iopath,pathio);
|
||||
//注册重定向
|
||||
if(redirecct_path(L)==-1){
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return NULL;
|
||||
}
|
||||
WITHOUT_REDIRECT:
|
||||
|
||||
@ -27,6 +27,12 @@ typedef struct lua_runner
|
||||
|
||||
void *lua_obj;//cpp对象,指向在cpp中封装的luarunner对象
|
||||
|
||||
// typed interop:最近一次调用的结果类型与值(镜像 Lua_runner 同名字段)
|
||||
int tresult_type; // 0=nil, 1=bool, 2=int, 3=num, 4=str
|
||||
long long tresult_int;
|
||||
double tresult_num;
|
||||
int tresult_bool;
|
||||
|
||||
}lua_runner;
|
||||
/*内部使用结构体,仓颉无需关心*/
|
||||
|
||||
@ -75,6 +81,56 @@ int unloadfunction(void *selfd,const char *name);
|
||||
/// @return 成功返回0,失败返回-1,并将lua出错原因拷贝至result中
|
||||
int callfunction(void *selfd,const char *name,const char *arg);
|
||||
|
||||
/*-------------typed interop(v0.2.2)------------------------*/
|
||||
// 原始类型直通映射:仓颉 Int64/Float64/Bool 与 Lua integer/number/boolean
|
||||
// 直接互转,无需序列化为字符串。调用后用 result_type/result_int/result_num/
|
||||
// result_bool/getresult 读取结果。
|
||||
|
||||
/// @brief 按名称调用预加载函数,传递 Int64 参数(Lua integer)
|
||||
/// @return 成功返回0,失败返回-1
|
||||
int callfunction_int(void *selfd,const char *name,long long val);
|
||||
|
||||
/// @brief 按名称调用预加载函数,传递 Float64 参数(Lua number)
|
||||
int callfunction_num(void *selfd,const char *name,double val);
|
||||
|
||||
/// @brief 按名称调用预加载函数,传递 Bool 参数(Lua boolean)
|
||||
int callfunction_bool(void *selfd,const char *name,int val);
|
||||
|
||||
/// @brief 按名称调用预加载函数,不传参数
|
||||
int callfunction_void(void *selfd,const char *name);
|
||||
|
||||
/// @brief 运行脚本,传递 Int64 参数
|
||||
int run_int(void *selfd,const char *path,long long val);
|
||||
|
||||
/// @brief 运行脚本,传递 Float64 参数
|
||||
int run_num(void *selfd,const char *path,double val);
|
||||
|
||||
/// @brief 运行脚本,传递 Bool 参数
|
||||
int run_bool(void *selfd,const char *path,int val);
|
||||
|
||||
/// @brief 运行脚本,不带参数
|
||||
int run_void(void *selfd,const char *path);
|
||||
|
||||
#define CJT_NIL 0
|
||||
#define CJT_BOOL 1
|
||||
#define CJT_INT 2
|
||||
#define CJT_NUM 3
|
||||
#define CJT_STR 4
|
||||
|
||||
/// @brief 获取最近一次 typed 调用的结果类型
|
||||
/// @return CJT_NIL/CJT_BOOL/CJT_INT/CJT_NUM/CJT_STR
|
||||
int result_type(void *selfd);
|
||||
|
||||
/// @brief 获取最近一次 typed 调用的整数结果(非整型结果时为转换值)
|
||||
long long result_int(void *selfd);
|
||||
|
||||
/// @brief 获取最近一次 typed 调用的浮点结果(非浮点结果时为转换值)
|
||||
double result_num(void *selfd);
|
||||
|
||||
/// @brief 获取最近一次 typed 调用的布尔结果
|
||||
int result_bool(void *selfd);
|
||||
/*-------------typed interop------------------------*/
|
||||
|
||||
/// @brief 运行lua脚本
|
||||
/// @param selfd init_lua_runner返回的void指针
|
||||
/// @param path 脚本路径
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "lua_runner.hpp"
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -13,7 +14,7 @@ Lua_runner::Lua_runner(const char *path)
|
||||
this->L = luaL_newstate();
|
||||
errno = 0;//清除老错误信息
|
||||
if(this->L == NULL){
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return ;
|
||||
}
|
||||
luaL_openlibs(this->L);//创建lua状态机,打开标准库
|
||||
@ -24,8 +25,8 @@ Lua_runner::Lua_runner(const char *path)
|
||||
|
||||
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;//加载默认路径*/
|
||||
"package.path = \";./luapkg/?/init.lua\"") != LUA_OK)//TODO 修改加载库的默认路径
|
||||
errno = LUAERR_INIT_FAIL;//加载默认路径*/
|
||||
if(path !=NULL)
|
||||
{
|
||||
char buf[1024];
|
||||
@ -33,10 +34,15 @@ Lua_runner::Lua_runner(const char *path)
|
||||
"package.path = package.path .. \";%s\"",
|
||||
path);
|
||||
if(luaL_dostring(this->L,buf) != LUA_OK)//加载用户路径
|
||||
errno = NAPI_LUA_INITFAIL;
|
||||
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()
|
||||
@ -59,13 +65,13 @@ bool Lua_runner::check_luastatue()
|
||||
/*检查lua状态机状况*/
|
||||
if(this->L == NULL)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return false;
|
||||
}
|
||||
//分为两部分写,防止空指针访问
|
||||
if(lua_status(this->L) != LUA_OK)
|
||||
{
|
||||
errno = NAPI_LUA_STATE_ERROR;
|
||||
errno = LUAERR_LUA_STATE;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -86,19 +92,19 @@ int Lua_runner::load_lib(const char *path,const char *name)
|
||||
}
|
||||
if(!this->check_file_exists(path))
|
||||
{
|
||||
errno = NAPI_LOAD_FILE_ERROR;
|
||||
errno = LUAERR_LOAD_FILE;
|
||||
return -1;
|
||||
}
|
||||
if(this->pkg_cont>=MAX_LUA_LIB)
|
||||
{
|
||||
errno = NAPI_LUALIB_LOAD_OVER_STACK;
|
||||
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 =NAPI_LOAD_FILE_ERROR;
|
||||
errno =LUAERR_LOAD_FILE;
|
||||
lua_pop(this->L,1);
|
||||
return -1;
|
||||
}
|
||||
@ -122,7 +128,7 @@ int Lua_runner::unload_lib(const char *name)
|
||||
}
|
||||
if(sig == -1)
|
||||
{
|
||||
errno = NAPI_UNLOADLIB_FAIL;
|
||||
errno = LUAERR_UNLOADLIB_FAIL;
|
||||
return -1;//没有查到返回异常(尝试卸载未加载的库)
|
||||
}
|
||||
/*检查lua状态*/
|
||||
@ -179,12 +185,12 @@ int Lua_runner::loadfunction(const char *path,const char *name)
|
||||
return -1;
|
||||
if(!this->check_file_exists(path))
|
||||
{
|
||||
errno = NAPI_LOAD_FILE_ERROR;
|
||||
errno = LUAERR_LOAD_FILE;
|
||||
return -1;
|
||||
}
|
||||
if(this->func_cont >= MAX_LUA_FUNC)
|
||||
{
|
||||
errno = NAPI_LOAD_FUNCTION_OVER;
|
||||
errno = LUAERR_FUNC_OVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
// 检查是否已存在同名函数
|
||||
@ -192,7 +198,7 @@ int Lua_runner::loadfunction(const char *path,const char *name)
|
||||
{
|
||||
if(strcmp(this->funcs[i].name, name) == 0)
|
||||
{
|
||||
errno = NAPI_FUNCTION_NOT_FOUND;
|
||||
errno = LUAERR_FUNCTION_NOT_FOUND;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -202,7 +208,7 @@ int Lua_runner::loadfunction(const char *path,const char *name)
|
||||
{
|
||||
const char *ret = lua_tostring(this->L, -1);
|
||||
this->reslt = ret;
|
||||
errno = NAPI_LOAD_FILE_ERROR;
|
||||
errno = LUAERR_LOAD_FILE;
|
||||
lua_pop(this->L, 1);
|
||||
return -1;
|
||||
}
|
||||
@ -210,7 +216,7 @@ int Lua_runner::loadfunction(const char *path,const char *name)
|
||||
// 2. 执行 chunk(顶层代码),期望返回一个函数
|
||||
if(lua_pcall(this->L, 0, 1, 0) != LUA_OK)
|
||||
{
|
||||
errno = NAPI_SCRIPT_ERROR;
|
||||
errno = LUAERR_SCRIPT_ERROR;
|
||||
this->reslt = lua_tostring(this->L, -1);
|
||||
lua_pop(this->L, 1);
|
||||
return -1;
|
||||
@ -219,7 +225,7 @@ int Lua_runner::loadfunction(const char *path,const char *name)
|
||||
// 3. 检查栈顶是否为函数
|
||||
if(!lua_isfunction(this->L, -1))
|
||||
{
|
||||
errno = NAPI_FUNCTION_NOT_VALID;
|
||||
errno = LUAERR_FUNCTION_INVALID;
|
||||
lua_pop(this->L, 1);
|
||||
return -1;
|
||||
}
|
||||
@ -248,7 +254,7 @@ int Lua_runner::unloadfunction(const char *name)
|
||||
}
|
||||
if(sig == -1)
|
||||
{
|
||||
errno = NAPI_FUNCTION_NOT_FOUND;
|
||||
errno = LUAERR_FUNCTION_NOT_FOUND;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -268,6 +274,98 @@ int Lua_runner::unloadfunction(const char *name)
|
||||
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())
|
||||
@ -285,7 +383,7 @@ int Lua_runner::callfunction(const char *name,const char *arg)
|
||||
}
|
||||
if(sig == -1)
|
||||
{
|
||||
errno = NAPI_FUNCTION_NOT_FOUND;
|
||||
errno = LUAERR_FUNCTION_NOT_FOUND;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -299,23 +397,88 @@ int Lua_runner::callfunction(const char *name,const char *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)
|
||||
{
|
||||
if(lua_isstring(this->L, -1))
|
||||
this->reslt = lua_tostring(this->L, -1);
|
||||
lua_pop(this->L, 1);
|
||||
finish_call(pre_top, argcount, true);//记录结果并弹出(预加载函数不参与管道)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = NAPI_SCRIPT_ERROR;
|
||||
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状态机状态
|
||||
@ -332,7 +495,7 @@ int Lua_runner::run(const char *path,const char *arg)
|
||||
}
|
||||
if(this->pkg_cont <= 0)//检查是否有可调用chunk
|
||||
{
|
||||
errno = NAPI_NOCHUNK_FOUND;
|
||||
errno = LUAERR_NOCHUNK_FOUND;
|
||||
return -1;
|
||||
}
|
||||
int func_index = this->pkgs[this->pkg_cont-1].ref - 1;
|
||||
@ -340,19 +503,20 @@ int Lua_runner::run(const char *path,const char *arg)
|
||||
int argcount = top - func_index;//获取入参数量
|
||||
if(argcount<0)
|
||||
{
|
||||
errno = NAPI_LUA_STACK_ERROR;
|
||||
errno = LUAERR_LUA_STACK;
|
||||
return -1;
|
||||
}//检查参数数量
|
||||
int pre_top = top;
|
||||
if(lua_pcall(this->L,argcount,LUA_MULTRET,0)== LUA_OK)
|
||||
{
|
||||
if(lua_isstring(this->L,-1))
|
||||
this->reslt = lua_tostring(this->L,-1);
|
||||
//管道模式:结果留在栈上供下一个节点使用,仅记录类型
|
||||
finish_call(pre_top, argcount, false);
|
||||
this->pkg_cont--;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = NAPI_SCRIPT_ERROR;
|
||||
errno = LUAERR_SCRIPT_ERROR;
|
||||
this->reslt = lua_tostring(this->L,-1);
|
||||
this->pkg_cont--;
|
||||
lua_pop(L,1);//错误出栈
|
||||
@ -360,22 +524,180 @@ int Lua_runner::run(const char *path,const char *arg)
|
||||
}
|
||||
}
|
||||
|
||||
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 = NAPI_ERROR_FUNCS;
|
||||
errno = LUAERR_CALLBACK;
|
||||
return -1;
|
||||
}
|
||||
if(luaL_dostring(this->L,target) != LUA_OK)
|
||||
{
|
||||
errno = NAPI_ERROR_FUNCS;
|
||||
errno = LUAERR_CALLBACK;
|
||||
this->reslt = lua_tostring(this->L,-1);
|
||||
lua_pop(L,1);//错误出栈
|
||||
return -1;
|
||||
}
|
||||
if(lua_gettop(this->L) == 0) {
|
||||
errno = NAPI_SCRIPT_BAD_RET;
|
||||
errno = LUAERR_SCRIPT_BAD_RET;
|
||||
this->reslt = "";
|
||||
return -1;
|
||||
}
|
||||
@ -385,7 +707,7 @@ int Lua_runner::dostring(const char *target)
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
errno = NAPI_SCRIPT_BAD_RET;
|
||||
errno = LUAERR_SCRIPT_BAD_RET;
|
||||
lua_pop(L,1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -24,6 +24,13 @@ typedef struct loaded_function
|
||||
|
||||
}ld_func;
|
||||
|
||||
// 结果类型标记(typed interop,v0.2.2)
|
||||
#define CJT_NIL 0
|
||||
#define CJT_BOOL 1
|
||||
#define CJT_INT 2
|
||||
#define CJT_NUM 3
|
||||
#define CJT_STR 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
class Lua_runner//lua运行器对象
|
||||
{
|
||||
@ -34,12 +41,31 @@ class Lua_runner//lua运行器对象
|
||||
int unload_lib(const char *name);//解除加载
|
||||
int loadfunction(const char *path,const char *name);//预加载函数(顶层执行,结果存入独立函数表)
|
||||
int unloadfunction(const char *name);//卸载预加载函数
|
||||
int callfunction(const char *name,const char *arg);//按名称调用已预加载的函数
|
||||
int run(const char *path = NULL,const char *arg = NULL);
|
||||
int callfunction(const char *name,const char *arg);//按名称调用已预加载的函数(字符串参数)
|
||||
int callfunction_int(const char *name, long long val);//按名称调用,传 Int64 参数
|
||||
int callfunction_num(const char *name, double val);//按名称调用,传 Float64 参数
|
||||
int callfunction_bool(const char *name, int val);//按名称调用,传 Bool 参数
|
||||
int callfunction_void(const char *name);//按名称调用,不带参数
|
||||
int run(const char *path = NULL,const char *arg = NULL);//运行脚本(字符串参数)
|
||||
int run_int(const char *path, long long val);//运行脚本,传 Int64 参数
|
||||
int run_num(const char *path, double val);//运行脚本,传 Float64 参数
|
||||
int run_bool(const char *path, int val);//运行脚本,传 Bool 参数
|
||||
int run_void(const char *path);//运行脚本,不带参数
|
||||
int clean();//清除状态机缓存
|
||||
int dostring(const char *target);
|
||||
std::string reslt;
|
||||
lua_State *get_lua_State();
|
||||
// typed interop:最近一次调用的结果类型与值(callfunction_*/run_* 更新)
|
||||
int last_result_type; // CJT_NIL/CJT_BOOL/CJT_INT/CJT_NUM/CJT_STR
|
||||
long long last_result_int;
|
||||
double last_result_num;
|
||||
int last_result_bool;
|
||||
// 内部辅助:读取 Lua 栈顶值并记录类型到 last_result_*
|
||||
void capture_result();
|
||||
// 计算 lua_pcall 实际返回值数量并记录结果;pop_results=true 时弹出全部返回值
|
||||
// (管道模式的 run_* 传 false 以保留栈上数据供后续节点使用)
|
||||
// 返回实际返回值数量
|
||||
int finish_call(int pre_top, int nargs, bool pop_results);
|
||||
private:
|
||||
lua_State *L;
|
||||
int pkg_cont;
|
||||
|
||||
Reference in New Issue
Block a user