/************************************************************************* > File Name: lua_plugin_data.c > Author: > Created Time: 2024-08 > Encoding : UTF-8 ************************************************************************/ /************************************************************************* * version * [ v0.1 ] * 08-06 * 1. 实现函数 * int lua_cdata_push_stack; * int lua_cdata_pop_stack; * void lua_cdata_destory; * struct lua_context * lua_context_new; * int lua_context_push_stack; * void lua_context_free; ************************************************************************/ #include "lua_plugin_manage_internal.h" /* * Function: lua_cdata_push_stack * Input: | lua_State * | state | 入栈数据使用的状态机 * | struct lua_cdata * | cdata | 需要入栈的数据 * Output: * Return: | -1 | 参数错误 * | 1 | 入栈数据类型有误 * | 0 | 入栈成功 * Description: 将一个数据元素入栈 */ int lua_cdata_push_stack( lua_State *state, struct lua_cdata *cdata) { if (__glibc_unlikely(!state || !cdata)) return -1; switch (cdata->cdata_type) { case DATATYPE_NIL: lua_pushnil(state); return 0; case DATATYPE_BOOL: lua_pushboolean(state, cdata->cdata_bool); return 0; case DATATYPE_INT: lua_pushinteger(state, cdata->cdata_int); return 0; case DATATYPE_NUM: lua_pushnumber(state, cdata->cdata_num); return 0; case DATATYPE_STRING: lua_pushstring(state, cdata->cdata_string); return 0; case DATATYPE_TABLE: lua_rawgeti(state, LUA_REGISTRYINDEX, cdata->cdata_table); return 0; case DATATYPE_POINTER: lua_pushlightuserdata(state, (void *)cdata->cdata_pointer); return 0; case DATATYPE_CONTEXT: lua_context_push_stack(cdata->cdata_context); return 0; default: LOGERROR("can't recorgnize data type %d", cdata->cdata_type); } return 1; } /* * Function: lua_cdata_pop_stack * Input: | lua_State * | state | 出栈数据使用的状态机 * | struct lua_cdata * | cdata | 保存出栈的元素 * Output: * Return: | -1 | 参数错误 * | -2 | 出栈数据类型有误 * | 0 | 出栈成功 * Description: 将一个数据元素出栈, 出栈过程中无法出栈context与table类型 * TODO: 扩展类型, 支持更多数据类型 */ int lua_cdata_pop_stack( lua_State *state, struct lua_cdata *cdata) { if (__glibc_unlikely(!state || !cdata)) return -1; if (!lua_gettop(state)) return 0; switch (lua_type(state, -1)) { case LUA_TNIL: cdata->cdata_type = DATATYPE_NIL; break; case LUA_TBOOLEAN: cdata->cdata_type = DATATYPE_BOOL; cdata->cdata_bool = lua_toboolean(state, -1); break; case LUA_TNUMBER: cdata->cdata_type = DATATYPE_NUM; cdata->cdata_num = lua_tonumber(state, -1); int try_int = (int)cdata->cdata_num; if ((double)try_int == cdata->cdata_num) { cdata->cdata_type = DATATYPE_INT; cdata->cdata_int = lua_tointeger(state, -1); } break; case LUA_TSTRING: cdata->cdata_type = DATATYPE_STRING; cdata->cdata_string = (char *)strdup(lua_tostring(state, -1)); break; case LUA_TLIGHTUSERDATA: cdata->cdata_type = DATATYPE_POINTER; cdata->cdata_pointer = (void *)lua_topointer(state, -1); break; default: /* 其他数据类型之后处理 */ LOGERROR("other lua type can't pop out, %d", lua_type(state, -1)); return -2; } lua_pop(state, 1); return 0; } /* * Function: lua_cdata_destory * Input: | struct lua_cdata * | cdata | 待销毁的data结构 * Output: * Return: * Description: 销毁是一个data结构, 释放内部占用内存 * 目前该函数仅数据类型为string的时候需要调用一次 */ void lua_cdata_destory(struct lua_cdata *cdata) { if (__glibc_unlikely(!cdata)) return; if (cdata->cdata_type == DATATYPE_STRING && cdata->cdata_string) free(cdata->cdata_string); return; } /* * Function: lua_context_new * Input: | lua_State * | state | 创建context使用的状态机 * Output: * Return: | NULL | 创建失败 * | pointer | 创建成功, 返回创建的context指针 * Description: 创建一个context结构, 由于context结构使用需要在状态机中生成引用值, 单独重写一个new函数 */ struct lua_context *lua_context_new(lua_State *state) { if (__glibc_unlikely(!state)) return NULL; lua_newtable(state); int ref_id = luaL_ref(state, LUA_REGISTRYINDEX); lua_settop(state, 0); if (ref_id == LUA_REFNIL) { return NULL; } struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context)); if (__glibc_unlikely(!new_context)) { luaL_unref(state, LUA_REGISTRYINDEX, ref_id); return NULL; } new_context->context_state = state; new_context->context_ref_id = ref_id; return new_context; } /* * Function: lua_context_push_stack * Input: | struct lua_context * | context | 待入栈的context结构 * Output: * Return: | 0 | 入栈成功 * | -1 | 参数错误 * Description: 将一个context入栈, 实际入栈流程与table一致 */ int lua_context_push_stack(struct lua_context *context) { if (luai_unlikely(!context)) return -1; lua_rawgeti(context->context_state, LUA_REGISTRYINDEX, context->context_ref_id); return 0; } /* * Function: lua_context_free * Input: | struct lua_context * | context | 释放一个context * Output: * Return: * Description: 释放一个context */ void lua_context_free(struct lua_context *context) { if (__glibc_unlikely(!context)) return; luaL_unref(context->context_state, LUA_REGISTRYINDEX, context->context_ref_id); free(context); return; }