diff --git a/src/lua_plugin_chunk.c b/src/lua_plugin_chunk.c new file mode 100644 index 0000000..a3b9586 --- /dev/null +++ b/src/lua_plugin_chunk.c @@ -0,0 +1,107 @@ +/************************************************************************* + > File Name: lua_plugin_chunk.c + > Author: + > Created Time: 2024-08 + > Encoding : UTF-8 + ************************************************************************/ + +/************************************************************************* + * 实现代码块相关操作 + * version + * [ v0.1 ] + * 08-12 + * 1. 实现函数 + * int lua_chunk_execute; + ************************************************************************/ +#include "lua_plugin_manage_internal.h" + +/* + * Function: lua_chunk_execute + * Input: | lua_State * | state | 执行该代码块使用的状态机 + * | int | ref_id | 代码块在状态机中的引用ID + * | int | pcount | 执行过程中传入的参数个数 + * | struct lua_cdata * | params | 执行过程中传入的参数 + * | int | rcount | 执行结束后返回值的个数 + * | struct lua_cdata * | returns | 执行结束后返回值 + * Output: + * Return: enum LUA_PLUGIN_RETURN + * Description: 在lua状态机中执行一段代码块, 执行的代码块需要提前在状态机中完成注册 + * 并已经生成相关的引用ID, 根据该ID进行调用 + */ +int lua_chunk_execute( + lua_State *state, + int ref_id, + int pcount, + struct lua_cdata *params, + int rcount, + struct lua_cdata *returns) +{ + if (__glibc_unlikely(!state || ref_id == LUA_REFNIL)) + return PARAM_ERR; + if ((pcount && !params) || (pcount < 0)) + return PARAM_ERR; + if ((rcount && !returns) || (rcount < 0)) + return PARAM_ERR; +#ifdef LUAPLUGIN_BASIC_UNITTEST + LOGDEBUG("now execute chunk, %p, %d\n", state, ref_id); +#endif + + /* 需要调用的函数入栈, 由于后续在读取参数个数的时候对栈操作较多, 需要先将函数入栈 */ + lua_rawgeti(state, LUA_REGISTRYINDEX, ref_id); + if (lua_gettop(state) == 0 || lua_type(state, -1) != LUA_TFUNCTION) + { + lua_settop(state, 0); + return CHUNK_TYPE_NOT_FUNCTION; + } + + /* 参数入栈 */ + int pushret = 0; + for (int i = 0; i < pcount; ++i) + { + if ((pushret = lua_cdata_push_stack(state, ¶ms[i]))) + { + lua_settop(state, 0); + return pushret; + } + } + + /* 执行该脚本并记录执行时间 */ + // clock_t start_time, end_time; + // start_time = clock(); + /* 调用该脚本 or 代码片段 */ + if (lua_pcall(state, pcount, LUA_MULTRET, 0)) + { + // end_time = clock(); + LOGERROR("run script failed, mess is %s\n", lua_tostring(state, -1)); + /* 仅函数运行过程中出错记入出错记录, 由于参数错误等原因导致的错误不记录 */ + lua_settop(state, 0); + return CHUNK_RUN_CODE_FAIL; + } + // end_time = clock(); + + /* 返回值出栈 */ + if (rcount > 0) + { + /* 如果rmaxcount为0, 说明在期望中不准备接收返回值, 也不必处理 */ + int count = lua_gettop(state); + if (count > rcount) + { + lua_settop(state, 0); + return CHUNK_RCOUNT_ERR; + } + int pop_ret = 0; + for (int i = (count - 1); i >= 0; --i) + { + if ((pop_ret = lua_cdata_pop_stack(state, &(returns[i])))) + { + lua_settop(state, 0); + return pop_ret; + } + } + } + + lua_settop(state, 0); + /* TODO: 记录耗时等数据 */ + + return SUCCESS; +} \ No newline at end of file