This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
niubinghui-luapluginmanage/docs/summaryDesign.md
2024-08-07 15:05:58 +08:00

31 KiB
Raw Blame History

LuaPluginManage

总述

整体功能

实现Lua插件的管理功能功能整体包括如下部分

  1. 状态机的管理及维护:功能包括状态机的创建、删除、初始化、获取运行状态等;
  2. 注册函数的管理功能C将函数注册至Lua环境中并可在Lua中进行调用提供函数检查功能为保证调用过程安全可靠在传入过程中对安全状态进行检查
  3. 数据的管理功能C将数据注册至Lua环境中如全局使用的字符串、版本信息、运行环境等
  4. 插件的管理功能将一个Lua插件加载至插件管理中与C插件一致将插件注册至stellar-plugin_manage及session_plugin_manage中
  5. 数据转化可以将Lua中的数据与C中的数据进行安全的数据转换用于在C中暂存Lua中保存的数据并可以对该数据进行修改、维护

状态机

状态机用于保存Lua运行虚拟机在运行过程中所有的环境表、注册表、堆栈、数据段、上下文等数据。Lua状态机是Lua运行过程中对外暴露的唯一数据结构其余数据结构均已经在Lua内部隐藏所有对Lua的操作均需要通过改变状态机的状态来实现。一个Lua状态机可以理解为一个Lua的线程该状态机和C的线程一样拥有独立的内存空间。
创建:安全的新建一个空的状态机
删除:释放一个状态机,删除其内部所有数据占用的内存并释放一个状态机实例
初始化状态机初始化过程中加载运行时必要的Lua组件并根据配置文件将各个Lua插件加载在状态机中
获取运行错误*:获取状态机运行过程中的错误
获取运行状态*:获取状态机运行状态,包括运行时间、加载插件数量、运行耗时等

函数

向Lua内部注册一个函数可供Lua程序在运行过程中调用。如向lua中传入数据结构时可通过注册函数的方式向Lua提供数据的获取方法。或通过注册函数向Lua提供其他模块的外部接口。
注册向Lua状态机中注册一个格式要求符合lpm_cbinding_function类型的函数该函数可供Lua脚本调用
删除从Lua状态机中删除一个C注册的函数
安全检查*提供一个标准化的定义方式在Lua插件编写过程中可通过该定义方式得知运行过程中存在的注册函数名称、参数类型等防止在调用过程中出错在Lua脚本加载前对其内部调用的C函数进行安全性检查检查如传入参数个数、参数类型等
自动化函数翻译*通过特定方法能够自动将一些C函数转换为Lua的注册函数格式

数据

向Lua内部注册一个函数可供Lua脚本在运行过程中使用。如向Lua中传入运行程序版本、运行环境信息、系统信息等。
注册:向状态机中注册一个全局变量,变量类型可以为数字、字符串;如需注册一个数据结构需同时注册该数据结构的成员获取方法
删除:从状态机中删除一个全局变量
数据范式化*将一段Lua数据范式化为一段json或其他特定格式方便输出或在其他程序中调用

插件

插件为一整个Lua功能模块与C中的插件含义相同。
插件加载:将一个插件加载至插件管理器中
插件卸载:从插件管理器中卸载一个插件
会话插件加载将一个会话插件加载至session_plugin_manage中
会话插件卸载从session_plugin_manage中删除一个会话插件
注册会话插件此功能仅在lua端暴露不在C接口中。在插件加载过程中可注册会话插件 订阅会话消息此功能仅在lua端暴露不在C接口中。在插件加载过程中可订阅一个会话中特定id的会话消息
处理会话消息:处理会话过程中的数据

数据转换*

将Lua数据翻译为C中可读可写可持久化保存的数据也可以将一个由Lua转换为C数据得到的序列化数据转换为Lua中的数据结构 Lua转换至C将Lua数据序列化成为C中一段内存数据 C转换至Lua将C中数据反序列化为Lua中一段数据

接口

外部接口

函数名称 参数 返回值 功能
lua_plugin_manage_init struct stellar * st
const char * config_file_path
创建的lua插件管理器实例指针 根据配置文件创建一个lua插件管理器实例并在函数内完成配置加载及初始化过程
lua_plugin_manage_exit struct lua_plugin_manage_schema * lua_plug_mgr void 清理一个lua插件管理器实例清除内部所有数据

内部接口

函数名称 参数 返回值 功能
lua_cbinding_functions lua_State *state 0表示成功其他表示失败返回值大于0时表示注册失败的元素个数 向lua状态机中注册函数函数定义在全局变量lua_bind_functions中
lua_cbinding_datas lua_State *state 0表示成功其他表示失败返回值大于0时表示注册失败的元素个数 向lua状态机中注册数据所有注册数据在状态机中作为全局变量存在所有注册数据保存在lua_bind_datas全局变量中
lua_cdata_push_stack lua_State *state
struct lua_cdata *cdata
0表示成功其他表示失败 将一个data结构入栈
lua_cdata_pop_stack lua_State *state
struct lua_cdata *cdata
0表示成功其他表示失败 从栈中弹出一个元素并保存在data结构中类型限制见函数实现部分
lua_cdata_destory struct lua_cdata *cdata void 销毁一个data结构只有string类型需要调用此函数其他的情况直接释放即可
lua_context_new lua_State *state 创建出的context实例 在状态机中生成一个context
lua_context_push_stack struct lua_context *context 0表示成功其他表示失败 将一个context入栈
lua_context_free struct lua_context *context void 释放一个context

C注册函数

函数名称 参数 返回值 功能
lpm_ctx_new_func struct session *sess
void *plugin_env
在该session中创建的context实例 session创建时调用
lpm_ctx_free_func struct session *sess
void *sess_ctx
void *plugin_env
void session销毁时调用

Lua注册函数

函数名称 参数 返回值 功能
lua_plugin_manage_session_regist lua_State * state 0无需处理返回值1需处理返回值 lua中调用该函数注册插件注册完成后调用方式为调用plugin_manage.register

总体设计

初始化

---
title: lua_plugin_manage_init
---
flowchart TD;
    start(["开始"]);
    createschema["calloc新的schema"];
    loadconfig["从配置文件中加载配置"];
    configcheck{"检查返回值"};
    threadcount["获取线程数量"];
    loadthread["每个线程中创建新的状态机"];
    freeschema["清理schema"];
    finish(["结束"]);

    start --> createschema
    createschema --> loadconfig
    loadconfig --> configcheck
    configcheck --> |<0|freeschema
    configcheck --> |>=0|threadcount;
    threadcount --> loadthread
    loadthread --> finish
    freeschema --> finish
  1. 创建一个新的schema实例
  2. 将配置文件中配置信息加载至schema实例中暂存
  3. 在schema中按照线程数量创建状态机并完成初始化

退出

---
title: lua_plugin_manage_exit
---
flowchart TD;
    start(["开始"]);
    freespecific["依次清理加载的配置信息"];
    freethread["依次关闭线程中的状态机"];
    freeschema["清理schema"];
    finish(["结束"]);

    start --> freespecific
    freespecific --> freethread
    freethread --> freeschema
    freeschema --> finish

功能模块

函数及全局变量注册

  1. 如果传入参数中包含space_name则将函数在Lua中注册为space_name.func_name形式
  2. 如果参数中没有space_name则将函数在Lua中注册为func_name形式
  3. 删除过程中只是将该函数的指针在Lua中修改为nil并不会真正删除需要等Lua下一次自动垃圾回收完成后才会真正完成删除
  4. 数据管理与函数管理流程相同不同之处在于函数删除时会检查Lua中数据类型是否为function但是在全局变量删除时不会做该校验

数据结构

/* 需要注册至lua中的函数 */
struct lua_binding_function
{
    /* 注册函数原型 */
    lua_CFunction binding_function;
    /* 注册至lua中的函数名称 */
    char *binding_function_name;
    /* 注册至lua中的命名空间名称 */
    char *binding_function_space_name;
};

/* 需要注册至lua状态机中的数据 */
struct lua_binding_data
{
    /* 注册的数据类型 */
    enum DATATYPE binding_data_type;
    /* 注册数数据值 */
    char *binding_data_value;
    /* 注册的数据名称 */
    char *binding_data_name;
    /* 注册至lua中的命名空间名称 */
    char *binding_data_space_name;
};

函数

函数名称 参数 返回值 功能
lua_cbinding_function lua_State *state
lua_CFunction bind_function
const char *function_name
const char *space_name
0表示成功其他表示失败 向lua状态机中注册一个函数
lua_cbinding_function_remove lua_State *state
const char *function_name
const char *space_name
0表示成功其他表示失败 从状态机中移除一个已经完成注册的函数
lua_cbinding_data lua_State *state
struct lua_binding_data *data
0表示成功其他表示失败 向lua状态机中注册一段数据该数据在状态机中作为全局变量存在
lua_cbinding_data_remove lua_State *state
const char *data_name
const char *space_name
0表示成功其他表示失败 从状态机中删除一个已经注册的数据,从状态机中删除该全局变量的引用
---
title: 函数注册 lua_cbinding_function
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    checkspace{"参数中是否有space_name"};
    getspace["状态机中获取space_name"];
    spacecheck{"space_name是否存在"};
    spacetablecheck{"space_name类型检查,是否为table类型"};
    createspace["创建space_name"];
    funccheck{"func_name是否存在"};
    createfunc["注册函数"];
    addfunc["func_name加入管理列表中"]
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|checkspace
    paramcheck --> |N|finish
    checkspace --> |Y|getspace
    checkspace --> |N|funccheck
    getspace --> spacecheck
    spacecheck --> |Y|spacetablecheck
    spacecheck --> |N|createspace
    createspace --> funccheck
    spacetablecheck --> |N|finish
    spacetablecheck --> |Y|funccheck
    funccheck --> |N|createfunc
    funccheck --> |Y|finish
    createfunc --> addfunc
    addfunc --> finish
---
title: 函数卸载 lua_cbinding_function_remove
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    funccheck{"func_name是否在管理列表中"}
    checkspace{"参数中是否有space_name"};
    spacecount{"space_name中是否仅有一个元素"}
    spacedelete["删除space_name"]
    funcdelete["删除func_name"]
    functype{"类型是否为LUA_TFUNCTION"}
    deletefunc["管理列表中删除func_name"]
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|funccheck
    paramcheck --> |N|finish
    funccheck --> |N|finish
    funccheck --> |Y|checkspace
    checkspace --> |Y|spacecount
    checkspace --> |N|funcdelete
    spacecount --> |Y|spacedelete
    spacedelete --> funcdelete
    spacecount --> |N|funcdelete
    funcdelete --> functype
    functype --> |Y|deletefunc
    functype --> |N|finish
    deletefunc --> finish
---
title: 数据注册 lua_cbinding_data
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    checkspace{"参数中是否有space_name"};
    getspace["状态机中获取space_name"];
    spacecheck{"space_name是否存在"};
    spacetablecheck{"space_name类型检查,是否为table类型"};
    createspace["创建space_name"];
    datacheck{"data_name是否存在"};
    createdata["注册数据"];
    adddata["data_name加入管理列表中"]
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|checkspace
    paramcheck --> |N|finish
    checkspace --> |Y|getspace
    checkspace --> |N|funccheck
    getspace --> spacecheck
    spacecheck --> |Y|spacetablecheck
    spacecheck --> |N|createspace
    createspace --> funccheck
    spacetablecheck --> |N|finish
    spacetablecheck --> |Y|datacheck
    datacheck --> |N|createdata
    datacheck --> |Y|finish
    createdata --> adddata
    adddata --> finish
---
title: 数据卸载 lua_cbinding_data_remove
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    datacheck{"data_name是否在管理列表中"}
    checkspace{"参数中是否有space_name"};
    spacecount{"space_name中是否仅有一个元素"}
    spacedelete["删除space_name"]
    datadelete["删除data_name"]
    deletedata["管理列表中删除data_name"]
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|datacheck
    paramcheck --> |N|finish
    datacheck --> |N|finish
    datacheck --> |Y|checkspace
    checkspace --> |Y|spacecount
    checkspace --> |N|datadelete
    spacecount --> |Y|spacedelete
    spacedelete --> datadelete
    spacecount --> |N|datadelete
    datadelete --> deletedata
    deletedata --> finish

Lua与C数据转换

  1. 根据不同的数据类型调用不同的Lua原生函数进行出入栈操作
  2. context本质是一个预分配并完成引用关联的lua-table在lua状态机中可以不受限制的使用
  3. 后续可能会根据数据类型进行lua和C的内存转换当前不支持内存共享使用
  4. lua元素在出栈过程中table类型的变量只创建引用并返回引用编号

数据结构

struct lua_cdata
{
    enum DATATYPE cdata_type;
    union
    {
        int cdata_bool;
        int cdata_int;
        double cdata_num;
        char *cdata_string;
        /* table暂时只有plugin_env场景下使用, 暂时使用索引进行操作 */
        int cdata_table;
        void *cdata_pointer;
        struct lua_context *cdata_context;
    };
};

struct lua_context
{
    lua_State *context_state;
    int context_ref_id;
};

状态机管理

  1. 每个线程中创建一个状态机,将该线程中加载的所有插件全部注册在该状态机中;

数据结构

struct lua_thread_state
{
    /* 创建状态机的线程ID */
    int thread_id;
    /* 已经插入的插件数量 */
    int thread_plugin_count;
    /* 生成的状态机 */
    lua_State *thread_state;
    // struct lua_pl_state_private * lua_thread_private;
    /* 该线程状态机中注册的插件列表 */
    UT_array *thread_env_array;
    /* 状态机的启动时间 */
    time_t thread_begin_time;
};

函数

函数名称 参数 返回值 功能
lua_plugin_manage_state_load struct lua_plugin_manage_schema *schema
int thread_count
>=0状态机创建成功的数量<0加载失败 在schema中根据线程数量创建多个状态机并完成状态机的初始化
thread_state_instance_init struct lua_thread_state *thread_state
int state_id
0表示成功其他表示失败 初始化一个状态机的实例包括创建lua_State、绑定函数、绑定全局变量等
thread_state_instance_destory void * elt void 销毁一个状态机,清空状态机中所有注册的插件并关闭状态机
thread_state_instance_load struct lua_thread_state *thread_state
struct lua_plugin_manage_schema *schema
0表示成功其他表示失败 根据配置数量创建plugin_env并依次调用插件加载函数完成插件的初始化
---
title: lua_plugin_manage_state_load
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    initstatearray["初始化schema中状态机队列"];
    checkstatecount{"状态机数量与线程数量一致"};
    createstate["创建新的状态机"];
    insertstate["创建完成的新状态机插入至schema队列中"];
    checkstateinit{"状态机全部完成初始化"};
    initstate["初始化状态机"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|initstatearray
    paramcheck --> |N|finish
    initstatearray --> checkstatecount;
    checkstatecount --> |Y|checkstateinit;
    checkstatecount --> |N|createstate;
    createstate --> insertstate;
    insertstate --> checkstatecount;
    checkstateinit --> |Y|finish
    checkstateinit --> |N|initstate;
    initstate --> checkstateinit;
---
title: thread_state_instance_init
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    newstate["创建状态机"];
    bindfunc["绑定函数"];
    binddata["绑定全局变量"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|newstate
    praamcheck --> |N|finish
    newstate --> bindfunc
    bindfunc --> binddata
    binddata --> finish
---
title: thread_state_instance_destory
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    unloadplugin["依次卸载所有插件"];
    closestate["关闭状态机"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|unloadplugin
    paramcheck --> |N|finish
    unloadplugin --> closestate
    closestate --> finish
---
title: thread_state_instance_load
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    plugincount{"完成所有插件初始化"};
    initpluginenv["初始化插件环境变量"];
    loadcount{"完成所有插件加载"};
    loadpluginenv["调用插件加载函数"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|plugincount
    paramcheck --> |N|finish
    plugincount --> |N|initpluginenv
    plugincount --> |Y|loadcount
    initpluginenv --> plugincount
    loadcount --> |Y|finish
    loadcount --> |N|loadpluginenv
    loadpluginenv --> loadcount

插件管理

整体原则每一个Lua插件在stellar的插件管理器中为一个单独的插件插件在C插件管理器中共用同一个函数在调用lua插件函数时根据插件的编号及注册使用的plugin_env查找插件的实际lua函数并完成调用

数据结构

/* 每一个插件的函数信息 */
struct lua_session_plugin
{
    /* 插件注册完成后得到的插件编号 */
    int plugin_id;

    /* ctx_new函数 */
    struct lua_script plugin_ctx_new_script;
    /* ctx_free函数 */
    struct lua_script plugin_ctx_free_script;
    /* on_message函数 */
    // struct lua_script plugin_on_message_script;
};

struct lua_plugin_env
{
    /* 插件注册的状态机 */
    lua_State *plugin_env_state;
    /* 该环境数据中包含的所有插件列表 */
    UT_array *plugin_env_plugin_array;

    /* 加载插件的lua函数 */
    struct lua_script plugin_env_load_func;
    /* 卸载插件的lua函数 */
    struct lua_script plugin_env_unload_func;

    /* 该插件运行环境数据的名称, 在创建时同时在状态机中创建该名称的命名空间 */
    /* 插件申请lua内的全局变量可以保存在该命名空间内, 防止被其他内容覆盖 */
    // char *plugin_env_name;

    /* 在lua中保存运行数据的引用ID */
    int plugin_env_ref_id; /* plugin_env */
};

函数

函数名称 参数 返回值 功能
session_plugin_instance_init struct lua_session_plugin *session_plugin
lua_State *state
int plugin_id
int new_refid
int free_refid
0表示成功其他表示失败 初始化一个运行在会话中的插件
session_plugin_instance_destory void *elt void 销毁一个运行在会话中的插件
plugin_env_instance_init struct lua_plugin_env *plugin_env
lua_State *state
struct lua_config_specific *specific
0表示成功其他表示失败 根据specific配置初始化一个plugin_env在此过程中仅将函数加载完成并未进行load函数调用load函数在状态机加载完成所有插件后统一调用
plugin_env_instance_destory void *elt void 销毁一个插件运行环境变量
---
title: session_plugin_instance_init
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    init["根据引用id分别初始化ctx_new及ctx_free"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|init
    paramcheck --> |N|finish
    init --> finish
---
title: session_plugin_instance_destory
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    delete["分别删除状态机中的引用"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|delete
    paramcheck --> |N|finish
    delete --> finish
---
title: plugin_env_instance_init
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    init["根据名称分别初始化ctx_new及ctx_free"];
    createenv["创建该插件pluginenv"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|init
    paramcheck --> |N|finish
    init --> createenv
    createenv --> finish
---
title: plugin_env_instance_destory
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    unload["调用unload函数"];
    unregist["卸载所有在该env中的插件"];
    deletefunc["删除load及unload函数在状态机中的引用"];
    deleteenv["删除创建的plugin_env"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|unload
    paramcheck --> |N|finish
    unload --> unregist
    unregist --> deletefunc
    deletefunc --> deleteenv
    deleteenv --> finish

脚本管理

数据结构

/* 一个可以运行的lua函数 */
/* 加载过程中生成引用, 后续使用过程中使用引用编号进行调用 */
struct lua_script
{
    /* 该函数注册时注册至的状态机, 运行过程中使用该状态机调用函数 */
    lua_State *script_state;
    /* 该函数的引用ID */
    int script_ref_id;

    /* 运行成功次数 */
    int script_run_success;
    /* 运行失败次数 */
    int script_run_failed;
    /* 最后一次运行开始时间 */
    clock_t script_last_ms_start;
    /* 最后一次运行结束时间 */
    clock_t script_last_ms_end;
    /* 运行总用时 */
    clock_t script_total_ms;
};

函数

函数名称 参数 返回值 功能
script_instance_init_byname struct lua_script *script
lua_State *state
const char *filepath
const char *funcname
0表示成功其他表示失败 根据文件名及函数名称从lua脚本中初始化一个脚本
script_instance_init_byrefid struct lua_script *script
lua_State *state
int ref_id
0表示成功其他表示失败 根据一个已经在状态机中生成引用的引用编号初始化一个脚本
script_instance_clean struct lua_script *script void 清理一个脚本实例
script_execute struct lua_script *script
int pcount
struct lua_cdata *param
int rmaxcount
struct lua_cdata *rvalue
0表示成功其他表示失败 运行一个脚本
---
title: script_instance_init_byname
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    fileload["加载lua文件"];
    findfunc["在文件中寻找对应函数"];
    createref["创建引用"];
    initscript["初始化脚本实例"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|fileload
    paramcheck --> |N|finish
    fileload --> findfunc
    findfunc --> createref
    createref --> initscript
    initscript --> finish
---
title: script_instance_init_byrefid
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    initscript["初始化脚本实例"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|initscript
    paramcheck --> |N|finish
    initscript --> finish
---
title: script_instance_clean
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    delete["状态机中删除该引用"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|delete
    paramcheck --> |N|finish
    delete --> finish
---
title: script_execute
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    getref["根据refid加载函数"];
    pushparam["传入参数"];
    logtime["记录时间"];
    execute["调用函数"];
    popreturn["取出参数"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|getref
    paramcheck --> |N|finish
    getref --> pushparam
    pushparam --> logtime
    logtime --> execute
    execute --> popreturn
    popreturn --> finish

配置管理

数据结构

/* 根据配置文件加载过程中保存插件信息的临时结构 */
struct lua_config_specific
{
    /* 插件需要使用的文件名 */
    char *config_specific_file;
    /* 插件名称 */
    // char *config_specific_name;
    /* 加载插件需要调用的函数名称 */
    char *config_specific_load_func;
    /* 卸载插件需要调用的函数名称 */
    char *config_specific_unload_func;
};

函数

函数名称 参数 返回值 功能
specific_instance_copy void *dst
const void *src
void 拷贝一个配置结构实例,拷贝过程为深拷贝
specific_instance_destory void *elt void 销毁一个配置结构实例,释放内部元素占用的内存
---
title: specific_instance_copy
---
flowchart TD;
    start(["开始"]);
    copy["依次拷贝内部成员"]
    finish(["结束"]);

    start --> copy
    copy --> finish
---
title: specific_instance_destory
---
flowchart TD;
    start(["开始"]);
    free["释放内部成员"]
    finish(["结束"]);

    start --> free
    free --> finish

C注册函数

函数名称 参数 返回值 功能
lpm_ctx_new_func struct session *sess
void *plugin_env
在该session中创建的context实例 session创建时调用
lpm_ctx_free_func struct session *sess
void *sess_ctx
void *plugin_env
void session销毁时调用
---
title: lpm_ctx_new_func
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    getpluginid["获取pluginid"];
    searchid["在pluginenv中查找该pluginid"];
    idcheck{"找到该id对应的插件"};
    newcontext["创建新的context"];
    execute["调用该插件实际的lua函数"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|getpluginid
    paramcheck --> |N|finish
    getpluginid --> searchid
    searchid --> idcheck
    idcheck --> |Y|newcontext
    idcheck --> |N|finish
    newcontext --> execute
    execute --> finish
---
title: lpm_ctx_free_func
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数检查"};
    getpluginid["获取pluginid"];
    searchid["在pluginenv中查找该pluginid"];
    idcheck{"找到该id对应的插件"};
    execute["调用该插件实际的lua函数"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|getpluginid
    paramcheck --> |N|finish
    getpluginid --> searchid
    searchid --> idcheck
    idcheck --> |Y|execute
    idcheck --> |N|finish
    execute --> finish

Lua注册函数

函数名称 参数 返回值 功能
lua_plugin_manage_session_regist lua_State * state 0无需处理返回值1需处理返回值 lua中调用该函数注册插件注册完成后调用方式为调用plugin_manage.register
---
title: lua_plugin_manage_session_regist
---
flowchart TD;
    start(["开始"]);
    paramcheck{"参数数量检查"};
    paramtypecheck{"参数类型检查"};
    getpluginenv["获取plugin_env"];
    getfreeref["将ctx_free函数创建引用"];
    getnewref["将ctx_new函数创建引用"];
    getstellar["获取stellar"];
    regist["调用stellar_session_plugin_register"];
    insertplugin["将插件id与函数对应关系插入plugin_env"];
    returnid["返回pluginid"];
    finish(["结束"]);

    start --> paramcheck
    paramcheck --> |Y|paramtypecheck
    paramcheck --> |N|finish
    paramtypecheck --> |Y|getpluginenv
    paramtypecheck --> |N|finish
    getpluginenv --> getfreeref
    getfreeref --> getnewref
    getnewref --> getstellar
    getstellar --> regist
    regist --> insertplugin
    insertplugin --> returnid
    returnid --> finish

安全性

重名的情况

在Lua中并不会校验是否存在重名变量、重名函数等出现重名的变量或函数会直接将旧的数据覆盖。

自定义数据冲突
自定义数据如果出现重名的情况,以先注册的为准,后续的函数或数据在注册中会报错

插件数据冲突
插件中的函数在初始化过程中会生成引用ID在Lua中被强引用的数据即使出现重名情况也不会被删除覆盖调用过程中根据引用ID进行调用函数重名不会产生影响 插件中的全局变量在初始化过程中可以通过提供给Lua的接口将全局变量注册成为一个状态机中的全局变量该全局变量与自定义数据全局变量的维护及保存逻辑一致后续注册插件过程中如果出现与当前全局变量冲突的数据会导致插件注册失败

自定义数据与插件数据冲突
自定义数据优先级高于插件数据,插件数据注册过程中如果与已存在的数据冲突会注册失败