diff options
| author | “pengxuanzheng” <[email protected]> | 2022-07-04 08:48:14 +0000 |
|---|---|---|
| committer | “pengxuanzheng” <[email protected]> | 2022-07-04 08:48:14 +0000 |
| commit | 512e852a76af00389c3340029144777aa7e69466 (patch) | |
| tree | 31ba8fbea566156dccd5c19d117cf0b69acb0ba5 | |
| parent | 16380940325160c0caaaad622e55ca26c44e976f (diff) | |
✨ feat(TSG-11123): 增加对lua上下文支持以及注册c函数支持
| -rw-r--r-- | example/multithread.cpp | 8 | ||||
| -rw-r--r-- | src/tsg_lua_func.cpp | 394 | ||||
| -rw-r--r-- | src/tsg_lua_interface.h | 43 |
3 files changed, 410 insertions, 35 deletions
diff --git a/example/multithread.cpp b/example/multithread.cpp index 53777da..b6090ce 100644 --- a/example/multithread.cpp +++ b/example/multithread.cpp @@ -28,10 +28,10 @@ typedef struct lua_script_info_s{ typedef struct lua_data_s{ char data[1024]; int data_len; -}lua_data_t; +}lua_test_data_t; typedef struct{ - lua_data_t data; + lua_test_data_t data; int thread_id; tsg_lua_handle lua; }userdata_t; @@ -74,7 +74,7 @@ void *lua_function(void *ptr) tsg_lua_handle L = NULL; userdata_t *userdata = (userdata_t *)ptr; - lua_data_t *data = &userdata->data; + lua_test_data_t *data = &userdata->data; int thread_id = userdata->thread_id; lua_script_info_t script_info[MAX_SCRIPT_NUM] = @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) char buf[1024]; int buf_len; userdata_t userdata[MAX_THREAD_NUM]; - lua_data_t *data = NULL; + lua_test_data_t *data = NULL; char *retval; #ifndef MIN diff --git a/src/tsg_lua_func.cpp b/src/tsg_lua_func.cpp index 4a95ab1..e4ffc8d 100644 --- a/src/tsg_lua_func.cpp +++ b/src/tsg_lua_func.cpp @@ -109,6 +109,13 @@ typedef struct{ char buff[TSG_LUA_READER_BUFFSIZE]; }tsg_lua_clfactory_file_t; +struct lua_private_info_t +{ + jmp_buf *lua_exception; + char lua_name[1024]; + void *userdata; +}; + //static jmp_buf lua_exception[TSG_MAX_LUA_ID]; static const char *syntax_error[] = @@ -413,8 +420,10 @@ static int c_lua_atpanic(lua_State *L) char err[255]; size_t len = 0; jmp_buf *lua_exception; + struct lua_private_info_t *lua_info = NULL; - lua_exception = (jmp_buf *)lua_getexdata(L); + lua_info = (struct lua_private_info_t *)lua_getexdata(L); + lua_exception = lua_info->lua_exception; if (lua_type(L, -1) == LUA_TSTRING) { s = (char *)lua_tolstring(L, -1, &len); @@ -466,28 +475,45 @@ int tsg_lua_memmem(lua_State *L) return 2; } -tsg_lua_handle tsg_lua_vm_create() +tsg_lua_handle tsg_lua_vm_create_with_name(const char *name) { + if (name == NULL) + { + name = "TSG"; + } lua_State *L; jmp_buf *lua_exception = (jmp_buf *)malloc(sizeof(jmp_buf)); if (lua_exception == NULL) { return NULL; } + + struct lua_private_info_t *lua_info = (struct lua_private_info_t *)malloc(sizeof(struct lua_private_info_t)); + if (lua_info == NULL) + { + free(lua_exception); + return NULL; + } L = luaL_newstate(); if (L == NULL) { free(lua_exception); + free(lua_info); return NULL; } - lua_setexdata(L, lua_exception); + lua_info->lua_exception = lua_exception; + int len = strlen(name); + memcpy(lua_info->lua_name, name, MIN(1023, len)); + lua_info->lua_name[len] = '\0'; + lua_info->userdata = NULL; + lua_setexdata(L, lua_info); lua_atpanic(L, c_lua_atpanic); luaL_openlibs(L); - lua_createtable(L, 0, 2); + lua_newtable(L); lua_pushcfunction(L, tsg_lua_memmem); lua_setfield(L, -2, "memmem"); - lua_setglobal(L, "TSG"); + lua_setglobal(L, name); #if 1 const char *code = "local ffi = require(\"ffi\")\n"\ "ffi.cdef[[char *memmem(const char *haystack, size_t haystacklen, const char *needle, size_t needlelen);]]\n"\ @@ -504,6 +530,11 @@ tsg_lua_handle tsg_lua_vm_create() return L; } +tsg_lua_handle tsg_lua_vm_create() +{ + return tsg_lua_vm_create_with_name((const char *)NULL); +} + int tsg_lua_exec_file(tsg_lua_handle lua, const char *script, const char *in, size_t in_len, char *out, size_t *out_len, size_t *out_type) { lua_State *L = (lua_State *)lua; @@ -513,6 +544,7 @@ int tsg_lua_exec_file(tsg_lua_handle lua, const char *script, const char *in, si int sharp = 0; tsg_lua_clfactory_file_t lf; jmp_buf *lua_exception; + struct lua_private_info_t *lua_info; int return_value = 0; if (L == NULL) @@ -544,7 +576,8 @@ int tsg_lua_exec_file(tsg_lua_handle lua, const char *script, const char *in, si return ERR_EXPECT_TYPE_IS_NIL; } - lua_exception = (jmp_buf *)lua_getexdata(L); + lua_info = (struct lua_private_info_t *)lua_getexdata(L); + lua_exception = lua_info->lua_exception; lf.extraline = 0; lf.sent_begin = 0; @@ -753,6 +786,7 @@ int tsg_lua_exec(tsg_lua_handle lua, const char *script, size_t script_len, cons int i = 0; int sharp = 0; tsg_lua_clfactory_buffer_t ls; + struct lua_private_info_t *lua_info = NULL; jmp_buf *lua_exception; int return_value = 0; @@ -787,7 +821,8 @@ int tsg_lua_exec(tsg_lua_handle lua, const char *script, size_t script_len, cons return ERR_EXPECT_TYPE_IS_NIL; } - lua_exception = (jmp_buf *)lua_getexdata(L); + lua_info = (struct lua_private_info_t *)lua_getexdata(L); + lua_exception = lua_info->lua_exception; ls.s = script; ls.size = script_len; @@ -1244,6 +1279,7 @@ int tsg_lua_uncache_script(tsg_lua_handle lua, size_t script_id) int tsg_lua_cache_exec(tsg_lua_handle lua, size_t script_id, const char *in, size_t in_len, char *out, size_t *out_len, size_t *out_type) { lua_State *L = (lua_State *)lua; + struct lua_private_info_t *lua_info = NULL; jmp_buf *lua_exception; int return_value = 0; @@ -1274,7 +1310,8 @@ int tsg_lua_cache_exec(tsg_lua_handle lua, size_t script_id, const char *in, siz } lua_settop(L, 0); - lua_exception = (jmp_buf *)lua_getexdata(L); + lua_info = (struct lua_private_info_t *)lua_getexdata(L); + lua_exception = lua_info->lua_exception; lua_rawgeti(L, LUA_REGISTRYINDEX, script_id); lua_getglobal(L, "TSG"); @@ -1372,19 +1409,354 @@ int tsg_destory_lua(tsg_lua_handle lua) { lua_State *L = (lua_State *)lua; jmp_buf *lua_exception = NULL; + struct lua_private_info_t *lua_info = NULL; if (L == NULL) { debuginfo("lua VM is null.", __FILE__, __LINE__); return ERR_LUAVM_ISNULL; } - lua_exception = (jmp_buf *)lua_getexdata(L); - if (lua_exception != NULL) + lua_info = (struct lua_private_info_t *)lua_getexdata(L); + if (lua_info != NULL) { - free(lua_exception); + if (lua_info->lua_exception != NULL) + { + free(lua_exception); + } + free(lua_info); } lua_close(L); return 0; } +int c_pull_param_from_lua(tsg_lua_handle lua, int *argc, struct lua_arg_t **argv) +{ + lua_State *L = (lua_State *)lua; + if (L == NULL) + { + return ERR_PARAMETER; + } + + *argc = lua_gettop(L); + if (*argc == 0) + { + *argv = NULL; + return 0; + } + + *argv = (struct lua_arg_t *)calloc(*argc, sizeof(struct lua_arg_t)); + // memset(argv, 0, argc * sizeof(struct lua_arg_t)); + + const char *str = NULL; + for (int i = 0; i < *argc; i++) + { + int type = lua_type(L, i - *argc); + switch (type) + { + case LUA_TBOOLEAN: + argv[i]->type = BOOLEAN; + argv[i]->flag = lua_toboolean(L, i - *argc); + break; + case LUA_TNUMBER: + argv[i]->type = INTEGER; + argv[i]->num = lua_tonumber(L, i - *argc); + break; + case LUA_TSTRING: + argv[i]->type = STRING; + str = lua_tostring(L, i - *argc); + argv[i]->len = strlen(str); + argv[i]->str = (char *)malloc(argv[i]->len+1); + memcpy(argv[i]->str, str, argv[i]->len); + argv[i]->str[argv[i]->len] = '\0'; + break; + default: + return ERR_LUA_FUNCTION_ARGV; + } + } + + return 0; +} + +int free_param_form_lua(int argc, lua_arg_t **argv) +{ + if (argc == 0 || *argv == NULL) + + for(int i = 0; i < argc; i++) + { + if (argv[i] == NULL) + { + continue; + } + if (argv[i]->type == STRING) + { + free(argv[i]->str); + argv[i]->str = NULL; + } + } + + free(*argv); + *argv = NULL; + + return 0; +} + +int c_push_string_into_lua(tsg_lua_handle lua, const char *str, size_t len) +{ + lua_State *L = (lua_State *)lua; + if (L == NULL || str == NULL) + { + return ERR_PARAMETER; + } + + lua_pushlstring(L, str, len); + return 0; +} + +int c_push_num_into_lua(tsg_lua_handle lua, long num) +{ + lua_State *L = (lua_State *)lua; + if (L == NULL ) + { + return ERR_PARAMETER; + } + + lua_pushinteger(L, num); + return 0; +} + +int c_push_bool_into_lua(tsg_lua_handle lua, bool flag) +{ + lua_State *L = (lua_State *)lua; + if (L == NULL) + { + return ERR_PARAMETER; + } + + lua_pushinteger(L, flag); + return 0; +} + +int c_push_nil_into_lua(tsg_lua_handle lua) +{ + lua_State *L = (lua_State *)lua; + if (L == NULL) + { + return ERR_PARAMETER; + } + + lua_pushnil(L); + return 0; +} + +int c_push_table_into_lua(tsg_lua_handle lua, const char **key_list, const char **value_list, size_t list_len) +{ + lua_State *L = (lua_State *)lua; + if (L == NULL || key_list == NULL || value_list == NULL) + { + return ERR_PARAMETER; + } + + lua_createtable(L, list_len, 0); + for (size_t i = 0; i < list_len; i++) + { + if (key_list[i] != NULL && value_list[i] != NULL) + { + // lua_pushliteral(L, key_list[i]); + // lua_pushliteral(L, value_list[i]); + lua_rawset(L, -3); + } + } + + return 0; +} + +void *lua_get_userdata(tsg_lua_handle L) +{ + struct lua_private_info_t * lua_info = (struct lua_private_info_t *)lua_getexdata(L); + + if (lua_info != NULL) + { + return lua_info->lua_name; + } + else + { + return NULL; + } +} + +int lua_register_function(tsg_lua_handle lua, const char *function_set, const char *function_name, lua_function_ptr const function) +{ + lua_State *L = (lua_State *)lua; + if (L == NULL || function_set == NULL || function_name == NULL || function == NULL) + { + return ERR_PARAMETER; + } + struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L); + if (lua_info == NULL) + { + return ERR_LUA_PRIVATE_INFO_IS_NIL; + } + + lua_getglobal(L, lua_info->lua_name); + lua_getfield(L, -1, function_set); + int ret = lua_type(L, -1); + if (ret != LUA_TTABLE) + { + lua_pop(L, 1); + lua_newtable(L); + lua_pushcfunction(L, function); + lua_setfield(L, -2, function_name); + lua_setfield(L, -2, function_set); + } + else + { + lua_pushcfunction(L, function); + lua_setfield(L, -2, function_name); + } + lua_settop(L, 0); + + return 0; +} + +struct lua_script_context +{ + int context_id; +}; +int lua_set_script_context(tsg_lua_handle L, struct lua_script_context *context) +{ + if (L == NULL || context == NULL) + { + return ERR_PARAMETER; + } + + lua_newtable(L); + int context_id = luaL_ref(L, LUA_REGISTRYINDEX); + if (context_id == LUA_REFNIL || context_id == LUA_NOREF) + { + return ERR_LUA_SET_CONTEXT_FAILED; + } + + // struct lua_private_info_t *lua_info = lua_getexdata(L); + // if (lua_info == NULL) + // { + // return ERR_LUA_PRIVATE_INFO_IS_NIL; + // } + + // lua_getglobal(L, lua_info->lua_name); + // lua_rawgeti(L, LUA_REGISTRYINDEX, context_id); + // lua_setfield(L, -2, "context"); + lua_settop(L, 0); + + context->context_id = context_id; + return 0; +} + +int lua_unset_script_context(tsg_lua_handle L, struct lua_script_context *context) +{ + if (L == NULL) + { + debuginfo("lua VM is null.", __FILE__, __LINE__); + return ERR_LUAVM_ISNULL; + } + if (context == NULL) + { + return ERR_PARAMETER; + } + + luaL_unref(L, LUA_REGISTRYINDEX, context->context_id); + + return 0; +} + +int lua_cache_exec_with_context(tsg_lua_handle L, size_t script_id, struct lua_data_t in, void *userdata, lua_script_context *context, struct lua_arg_t *outvalue) +{ + if (L == NULL) + { + debuginfo("lua VM is null.", __FILE__, __LINE__); + return ERR_LUAVM_ISNULL; + } + + if (outvalue == NULL || in.data == NULL || in.len == 0) + { + return ERR_PARAMETER; + } + + struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L); + if (lua_info == NULL) + { + return ERR_LUA_PRIVATE_INFO_IS_NIL; + } + + if (context != NULL && context->context_id != LUA_REFNIL && context->context_id != LUA_NOREF) + { + lua_info->userdata = userdata; + lua_getglobal(L, lua_info->lua_name); + lua_rawgeti(L, LUA_REGISTRYINDEX, context->context_id); + lua_setfield(L, -2, "context"); + } + + return tsg_lua_cache_exec(L, script_id, in.data, in.len, outvalue->str, &outvalue->len, &outvalue->type); +} + +int lua_exec_with_context(tsg_lua_handle L, struct lua_data_t script, struct lua_data_t in, void *userdata, lua_script_context *context, struct lua_arg_t *outvalue) +{ + if (L == NULL) + { + debuginfo("lua VM is null.", __FILE__, __LINE__); + return ERR_LUAVM_ISNULL; + } + + if (outvalue == NULL || in.data == NULL || in.len == 0 || script.data == NULL || script.len == 0) + { + return ERR_PARAMETER; + } + + struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L); + if (lua_info == NULL) + { + return ERR_LUA_PRIVATE_INFO_IS_NIL; + } + + lua_info->userdata = userdata; + if (context != NULL && context->context_id != LUA_REFNIL && context->context_id != LUA_NOREF) + { + lua_getglobal(L, lua_info->lua_name); + lua_rawgeti(L, LUA_REGISTRYINDEX, context->context_id); + lua_setfield(L, -2, "context"); + lua_settop(L, 0); + } + + return tsg_lua_exec(L, script.data, script.len, in.data, in.len, outvalue->str, &outvalue->len, &outvalue->type); +} + +int lua_exec_file_with_context(tsg_lua_handle L, const char *script, struct lua_data_t in, void *userdata, lua_script_context *context, struct lua_arg_t *outvalue) +{ + if (L == NULL) + { + debuginfo("lua VM is null.", __FILE__, __LINE__); + return ERR_LUAVM_ISNULL; + } + + if (outvalue == NULL || in.data == NULL || in.len == 0 || script == NULL) + { + return ERR_PARAMETER; + } + + struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L); + if (lua_info == NULL) + { + return ERR_LUA_PRIVATE_INFO_IS_NIL; + } + + lua_info->userdata = userdata; + if (context != NULL && context->context_id != LUA_REFNIL && context->context_id != LUA_NOREF) + { + lua_getglobal(L, lua_info->lua_name); + lua_rawgeti(L, LUA_REGISTRYINDEX, context->context_id); + lua_setfield(L, -2, "context"); + lua_settop(L, 0); + } + + return tsg_lua_exec_file(L, script, in.data, in.len, outvalue->str, &outvalue->len, &outvalue->type); +}
\ No newline at end of file diff --git a/src/tsg_lua_interface.h b/src/tsg_lua_interface.h index 17a49a1..0beef81 100644 --- a/src/tsg_lua_interface.h +++ b/src/tsg_lua_interface.h @@ -16,8 +16,8 @@ enum type struct lua_arg_t { - int type; - int len; //仅当type == STRING时有效 + size_t type; + size_t len; //仅当type == STRING时有效 union{ char *str; long num; @@ -82,12 +82,18 @@ enum err_value ERR_MEM_NOT_ENOUGH = -35, /* 空间不足 */ ERR_LUA_ID = -36, /* lua id 错误*/ ERR_EXPECT_TYPE_IS_NIL = -37, /* 预期脚本返回类型为空 */ - ERR_UNKNOWN = -38, /* 未知错误 */ + ERR_LUA_FUNCTION_ARGC = -38, /* lua 注册的C函数,调用时输入参数个数不匹配 */ + ERR_LUA_FUNCTION_ARGV = -39, /* lua 注册的C函数,调用时输入参数类型不匹配 */ + ERR_PARAMETER = -40, /* 参数错误 */ + ERR_LUA_PRIVATE_INFO_IS_NIL = -41, /* lua 私有信息为空 */ + ERR_LUA_SET_CONTEXT_FAILED = -42, /* lua 添加上下文失败 */ + ERR_UNKNOWN = -43, /* 未知错误 */ ERR_RETUNR_NIL = 1, /* 脚本执行成功,但是返回空*/ ERR_RETURN_TYPE_NOT_MATCH_EXPECT = 2, /* 脚本执行成功,但是返回值类型与预期不符 */ }; -typedef void* tsg_lua_handle; +struct lua_State; +typedef lua_State* tsg_lua_handle; /* 函数名:tsg_lua_vm_create * 返回值:tsg_lua_handle 成功,返回一个虚拟机, @@ -159,22 +165,13 @@ int tsg_lua_cache_exec(tsg_lua_handle L, size_t script_id, const char *in, size_ * 返回值: int 成功,返回0;失败返回错误值err_value */ int tsg_destory_lua(tsg_lua_handle L); -/* 函数名: lua_poll_interactive_stack_param - * 描述: 此函数用来获取当前C与LUA的交互栈的参数 - * 输入参数: tsg_lua_handle L 指定虚拟机 - * 输入参数: int argc 指定交互栈上应该返回多少个参数,参数个数不同,返回错误 - * 输入输出参数:lua_arg_t *argv 指定交互栈上返回的参数类型,参数类型不同,返回错误,参数类型相同,会记录该类型值 - * 返回值: int 成功,返回0;失败返回错误值err_value */ -int lua_poll_interactive_stack_param(tsg_lua_handle L, int argc, lua_arg_t *argv); - -/* 函数名: lua_push_interactive_stack_param - * 描述: 此函数用来获取当前C与LUA的交互栈的参数 - * 输入参数: tsg_lua_handle L 指定虚拟机 - * 输入参数: int argc 指定交互栈上应该返回多少个参数,参数个数不同,返回错误 - * 输入参数: lua_arg_t *argv 指定交互栈上返回的参数类型,参数类型不同,返回错误,参数类型相同,会记录该类型值 - * 输入参数: enum TYPE lua_type 将输入参数转换为指定类型并入到C与lua的交互栈上 - * 返回值: int 成功,返回0;失败返回错误值err_value */ -int lua_push_interactive_stack_param(tsg_lua_handle L, int argc, lua_arg_t *argv, enum type lua_type); +int c_pull_param_from_lua(tsg_lua_handle lua, int *argc, lua_arg_t **argv); +int free_param_form_lua(int argc, lua_arg_t **argv); +int c_push_num_into_lua(tsg_lua_handle lua, long num); +int c_push_bool_into_lua(tsg_lua_handle lua, bool flag); +int c_push_nil_into_lua(tsg_lua_handle lua); +int c_push_string_into_lua(tsg_lua_handle lua, const char *str, size_t len); +int c_push_table_into_lua(tsg_lua_handle lua, const char **key_list, const char **value_list, size_t list_len); /* 函数名: lua_get_userdata * 描述: 此函数用来获取exec系列函数设置的userdata @@ -234,4 +231,10 @@ int lua_exec_with_context(tsg_lua_handle L, struct lua_data_t script, struct lua * 输出参数: struct lua_arg_t *outvalue 脚本执行成功返回的内容 * 返回值: int 成功,返回0;失败返回 -1*/ int lua_exec_file_with_context(tsg_lua_handle L, struct lua_data_t script, struct lua_data_t in, void *userdata, lua_script_context *context, struct lua_arg_t *outvalue); + +/* 函数名:tsg_lua_vm_create_with_name + * 返回值:tsg_lua_handle 成功,返回一个虚拟机, + * 输入参数: char *name 虚拟机名称,可以在lua中找到该名字的全局变量,建议大写字母开头。如果为空,默认填写"TSG" + * 失败,返回NULL */ +tsg_lua_handle tsg_lua_vm_create_with_name(char *name); #endif |
