summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author“pengxuanzheng” <[email protected]>2022-07-04 08:48:14 +0000
committer“pengxuanzheng” <[email protected]>2022-07-04 08:48:14 +0000
commit512e852a76af00389c3340029144777aa7e69466 (patch)
tree31ba8fbea566156dccd5c19d117cf0b69acb0ba5
parent16380940325160c0caaaad622e55ca26c44e976f (diff)
✨ feat(TSG-11123): 增加对lua上下文支持以及注册c函数支持
-rw-r--r--example/multithread.cpp8
-rw-r--r--src/tsg_lua_func.cpp394
-rw-r--r--src/tsg_lua_interface.h43
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