feat: 实现loadFunction预加载函数能力 + AI辅助编程标识

- 新增 loadFunction/callFunction/unloadFunction 预加载函数 API
- 预加载语义:加载文件→顶层执行一次→返回函数存入Lua Registry→可多次调用
- 与管道模式(load/runScript)存储完全解耦:funcs[]+Registry vs pkgs[]+虚拟栈
- 新增错误码 5023/5024/5025
- 新增单元测试:仓颉侧 8 个 + C++ GTest 侧 11 个
- 本机以 Cangjie 1.1.0 实编译并通过功能运行验证
- README/doc 增加 AI 辅助编程标识及预加载函数模式说明
This commit is contained in:
JianFeeeee
2026-08-23 12:03:04 +08:00
parent 207082a1a0
commit 42e8b7676d
14 changed files with 759 additions and 6 deletions

View File

@ -25,7 +25,7 @@ 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;//加载默认路径*/
errno = NAPI_LUA_INITFAIL;//加载默认路径*/
if(path !=NULL)
{
char buf[1024];
@ -36,6 +36,7 @@ Lua_runner::Lua_runner(const char *path)
errno = NAPI_LUA_INITFAIL;
}
this->pkg_cont = 0;
this->func_cont = 0;
}
Lua_runner::~Lua_runner()
@ -160,12 +161,161 @@ int Lua_runner::clean()//进行新一轮调用前一定要先clean清除上个
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 = NAPI_LOAD_FILE_ERROR;
return -1;
}
if(this->func_cont >= MAX_LUA_FUNC)
{
errno = NAPI_LOAD_FUNCTION_OVER;
return -1;
}
// 检查是否已存在同名函数
for(int i = 0; i < this->func_cont; i++)
{
if(strcmp(this->funcs[i].name, name) == 0)
{
errno = NAPI_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 = NAPI_LOAD_FILE_ERROR;
lua_pop(this->L, 1);
return -1;
}
// 2. 执行 chunk顶层代码期望返回一个函数
if(lua_pcall(this->L, 0, 1, 0) != LUA_OK)
{
errno = NAPI_SCRIPT_ERROR;
this->reslt = lua_tostring(this->L, -1);
lua_pop(this->L, 1);
return -1;
}
// 3. 检查栈顶是否为函数
if(!lua_isfunction(this->L, -1))
{
errno = NAPI_FUNCTION_NOT_VALID;
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 = NAPI_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;
}
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 = NAPI_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;
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);
return 0;
}
else
{
errno = NAPI_SCRIPT_ERROR;
this->reslt = lua_tostring(this->L, -1);
lua_pop(this->L, 1);
return -1;
}
}
int Lua_runner::run(const char *path,const char *arg)
{
if(!this->check_luastatue())//检查lua状态机状态