脚本开发

本篇将介绍如何开发脚本语言动态扩展库,同时也会给出开发所需要的各类函数。

头文件

#include "mln_lang.h"

模块名

lang

开发流程

动态扩展库开发流程如下:

  1. 构造一个含有名为init函数的动态库,其中init的函数原型为:

    mln_lang_var_t *init(mln_lang_ctx_t *);
    

    mln_lang_var_t是脚本任务中函数返回值的类型,创建的方式可以参考mln_lang.h以及melang的各种内置函数实现。

    开发者可在init函数中加载各种脚本函数、集合、变量等内容。如果函数返回值为nil,则这与内置库的步骤4是类似的。

    init中的mln_lang_var_t返回值是在函数import调用结束时返回的。

  2. 使用时,在脚本中调用import函数引入此动态库,程序会调用init函数来将库内要加载的资源加载到脚本当前的作用域内。

函数/宏

开发者不仅可以使用这里给出的函数,也可以使用上一篇介绍的函数。例如Melang中eval函数的实现。

相关结构

struct mln_lang_var_s {
    mln_lang_ctx_t                  *ctx;//脚本任务结构
    mln_lang_var_type_t              type;//是否为引用类型
    mln_string_t                    *name;//变量名,匿名变量会置NULL
    mln_lang_val_t                  *val;//具体值
    mln_lang_set_detail_t           *in_set;//是否属于某个Set结构(即类定义)
    mln_lang_var_t                  *prev;
    mln_lang_var_t                  *next;
    mln_lang_var_t                  *prev;
    mln_lang_var_t                  *next;
    mln_uauto_t                      ref;//被引用的次数
};

struct mln_lang_val_s {
    mln_lang_ctx_t                  *ctx;//脚本任务结构
    struct mln_lang_val_s           *prev;
    struct mln_lang_val_s           *next;
    union {
        mln_s64_t                i;
        mln_u8_t                 b;
        double                   f;
        mln_string_t            *s;
        mln_lang_object_t       *obj;
        mln_lang_func_detail_t  *func;
        mln_lang_array_t        *array;
        mln_lang_funccall_val_t *call;
    } data; //具体数据
    mln_s32_t                        type;//数据类型
    mln_u32_t                        ref;//值结构被引用次数
    mln_lang_val_t                  *udata;//用于响应式编程
    mln_lang_func_detail_t          *func;//用于响应式编程
    mln_u32_t                        not_modify:1;//本值结构是否允许被修改
};

struct mln_lang_symbol_node_s {
    mln_string_t                    *symbol;//符号字符串
    mln_lang_ctx_t                  *ctx;//脚本任务结构
    mln_lang_symbol_type_t           type;//符号类型 类定义(M_LANG_SYMBOL_SET)还是变量(M_LANG_SYMBOL_VAR)
    union {
        mln_lang_var_t          *var;
        mln_lang_set_detail_t   *set;
    } data;
    mln_uauto_t                      layer;//所属作用域层数
    mln_lang_hash_bucket_t          *bucket;//所属符号表桶结构
    struct mln_lang_symbol_node_s   *prev;
    struct mln_lang_symbol_node_s   *next;
    struct mln_lang_symbol_node_s   *scope_prev;
    struct mln_lang_symbol_node_s   *scope_next;
};

在脚本中,这前两个结构是脚本中最主要的结构。可以看到mln_lang_var_tmln_lang_val_t的一层包装。mln_lang_val_t用于存放具体数值、字符串等内容。而mln_lang_var_t一般会作为函数参数、返回值、数组元素值的封装结构。

之所以封装一层是为了两方面:

  1. 函数参数的引用功能
  2. 将变量名与变量值进行映射

我们可以将前者称为变量结构,后者称为值结构。

值结构的类型包含如下:

  • M_LANG_VAL_TYPE_NIL 空值
  • M_LANG_VAL_TYPE_INT 整数
  • M_LANG_VAL_TYPE_BOOL 布尔值
  • M_LANG_VAL_TYPE_REAL 实数
  • M_LANG_VAL_TYPE_STRING 字符串
  • M_LANG_VAL_TYPE_OBJECT 对象
  • M_LANG_VAL_TYPE_FUNC 函数定义
  • M_LANG_VAL_TYPE_ARRAY 数组
  • M_LANG_VAL_TYPE_CALL 函数调用

mln_lang_var_new

mln_lang_var_t *mln_lang_var_new(mln_lang_ctx_t *ctx, mln_string_t *name, mln_lang_var_type_t type, mln_lang_val_t *val, mln_lang_set_detail_t *in_set);

描述:创建变量结构,参数含义依次为:

  • ctx脚本结构
  • name变量名,若无则置NULL
  • type 变量类型,引用(M_LANG_VAR_REFER)还是复制(M_LANG_VAR_NORMAL)。
  • val对应的值结构。
  • in_set是否属于某个Set(类定义),若无则置NULL

返回值:成功则返回结构指针,否则返回NULL

mln_lang_var_free

void mln_lang_var_free(void *data);

描述:释放mln_lang_var_t类型指针data的资源,包括其内部的值结构。

返回值:无

mln_lang_var_ref

mln_lang_var_ref(var)

描述:创建变量结构的引用。当释放时,若引用大于1,则不会真正释放变量结构。

返回值:mln_lang_var_t类型指针

mln_lang_var_val_get

mln_lang_var_val_get(var)

描述:获取mln_lang_var_t类型指针var的值结构。

返回值:mln_lang_val_t类型指针

mln_lang_val_not_modify_set

mln_lang_val_not_modify_set(val)

描述:设置mln_lang_val_t类型指针val为不可更改。

返回值:无

mln_lang_val_not_modify_isset

mln_lang_val_not_modify_isset(val)

描述:判断mln_lang_val_t类型指针val是否为不可更改。

返回值:不可更改返回非0,否则返回0

mln_lang_val_not_modify_reset

mln_lang_val_not_modify_reset(val)

描述:设置mln_lang_val_t类型指针val为可更改。

返回值:无

mln_lang_var_dup

mln_lang_var_t *mln_lang_var_dup(mln_lang_ctx_t *ctx, mln_lang_var_t *var);

描述:复制var。对于数组和对象类型的变量,只引用不复制。复制品使用ctx中的内存池结构进行内存分配。

返回值:变量结构指针。

mln_lang_var_value_set

int mln_lang_var_value_set(mln_lang_ctx_t *ctx, mln_lang_var_t *dest, mln_lang_var_t *src);

描述:将src中的值赋给dest。若dest中原本有值,则会将该值释放。对于数组和对象,仅引用,不复制。对于字符串,本函数完全复制一份。

返回值:成功则返回0,否则返回-1

mln_lang_var_value_set_string_ref

int mln_lang_var_value_set_string_ref(mln_lang_ctx_t *ctx, mln_lang_var_t *dest, mln_lang_var_t *src);

描述:将src中的值赋给dest。若dest中原本有值,则会将该值释放。对于数组和对象,仅引用,不复制。对于字符串,本函数仅引用不复制。

返回值:成功则返回0,否则返回-1

mln_lang_var_val_type_get

mln_s32_t mln_lang_var_val_type_get(mln_lang_var_t *var);

描述:获取变量的值的类型,类型定义参见相关结构部分。

返回值:类型值

mln_lang_ctx_global_var_add

int mln_lang_ctx_global_var_add(mln_lang_ctx_t *ctx, mln_string_t *name, void *val, mln_u32_t type);

描述:给脚本任务ctx增加一个最外层(也算是全局)变量。变量名为name,变量值为val,值的类型为typetype满足相关结构小节处定义的类型。若为字符串类型,则新增变量会使用mln_string_ref进行引用,因此要注意val为栈中分配时可能造成的问题。

返回值:成功则返回0,否则返回-1

mln_lang_var_create_call

mln_lang_var_t *mln_lang_var_create_call(mln_lang_ctx_t *ctx, mln_lang_funccall_val_t *call);

描述:创建一个函数调用类型的变量。此变量仅在脚本核心中被使用,这里仅顺带提一下。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_nil

mln_lang_var_t *mln_lang_var_create_nil(mln_lang_ctx_t *ctx, mln_string_t *name);

描述:创建一个空类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_obj

mln_lang_var_t *mln_lang_var_create_obj(mln_lang_ctx_t *ctx, mln_lang_set_detail_t *in_set, mln_string_t *name);

描述:创建一个对象类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。in_set为对象所属类(Set),本函数仅对in_set做引用,而不会完全复制。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_true

mln_lang_var_t *mln_lang_var_create_true(mln_lang_ctx_t *ctx, mln_string_t *name);

描述:创建一个布尔真变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_false

mln_lang_var_t *mln_lang_var_create_false(mln_lang_ctx_t *ctx, mln_string_t *name);

描述:创建一个布尔假变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_int

mln_lang_var_t *mln_lang_var_create_int(mln_lang_ctx_t *ctx, mln_s64_t off, mln_string_t *name);

描述:创建一个整数类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_real

mln_lang_var_t *mln_lang_var_create_real(mln_lang_ctx_t *ctx, double f, mln_string_t *name);

描述:创建一个实数类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_bool

mln_lang_var_t *mln_lang_var_create_bool(mln_lang_ctx_t *ctx, mln_u8_t b, mln_string_t *name);

描述:创建一个布尔类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。b0时为布尔假,否则为布尔真。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_string

mln_lang_var_t *mln_lang_var_create_string(mln_lang_ctx_t *ctx, mln_string_t *s, mln_string_t *name);

描述:创建一个空类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。本函数会完全复制一份s

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_ref_string

mln_lang_var_t *mln_lang_var_create_ref_string(mln_lang_ctx_t *ctx, mln_string_t *s, mln_string_t *name);

描述:创建一个空类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。本函数仅会用mln_string_ref引用s,因此注意s为栈中分配的内存时所带来的影响。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_var_create_array

mln_lang_var_t *mln_lang_var_create_array(mln_lang_ctx_t *ctx, mln_string_t *name);

描述:创建一个数组类型变量。若该变量不需要变量名,则nameNULL。注意,这里name会被mln_string_ref进行引用,因此需要注意name为栈中分配的内存时所带来的影响。创建完毕后,为空数组。

返回值:成功则返回变量类型指针,否则返回NULL

mln_lang_condition_is_true

int mln_lang_condition_is_true(mln_lang_var_t *var);

描述:判断var变量的值是否为逻辑真。

返回值:真则返回1,否则返回0

mln_lang_ctx_set_ret_var

void mln_lang_ctx_set_ret_var(mln_lang_ctx_t *ctx, mln_lang_var_t *var);

描述:设置当前脚本任务ctx的返回值为var。此处对var为引用而非复制。

返回值:无

mln_lang_val_new

mln_lang_val_t *mln_lang_val_new(mln_lang_ctx_t *ctx, mln_s32_t type, void *data);

描述:创建值结构。type类型参见相关结构小节。data根据type不同,则其类型也不同,具体类型参见相关结构中结构体中共同体部分的类型。但需要注意,本参数是指针类型,即整型就是mln_s64_t *而非mln_s64_t类型强制转换。

返回值:成功则返回值结构指针,否则返回NULL

mln_lang_val_free

void mln_lang_val_free(mln_lang_val_t *val);

描述:释放值结构。

返回值:无

mln_lang_symbol_node_search

mln_lang_symbol_node_t *mln_lang_symbol_node_search(mln_lang_ctx_t *ctx, mln_string_t *name, int local);

描述:在脚本任务ctx的符号表中查询名字为name的符号。若仅是在当前函数作用域内进行查询,则local非0,否则为0

返回值:若存在则返回符号结构指针,否则返回NULL

mln_lang_symbol_node_join

int mln_lang_symbol_node_join(mln_lang_ctx_t *ctx, mln_lang_symbol_type_t type, void *data);

描述:将类型为typedata加入符号表。type值为:

  • M_LANG_SYMBOL_VAR - 变量
  • M_LANG_SYMBOL_SET - 类

根据type的不同,data的类型也不同:

  • mln_lang_var_t *
  • mln_lang_set_detail_t *

本函数处理时,data为直接引用而非复制。

注意:变量必须有变量名。

返回值:成功则返回0,否则返回-1

mln_lang_symbol_node_upper_join

int mln_lang_symbol_node_upper_join(mln_lang_ctx_t *ctx, mln_lang_symbol_type_t type, void *data);

描述:将类型为typedata加入上一层作用域的符号表,若已是最外层,则加入最外层的符号表。type值为:

  • M_LANG_SYMBOL_VAR - 变量
  • M_LANG_SYMBOL_SET - 类

根据type的不同,data的类型也不同:

  • mln_lang_var_t *
  • mln_lang_set_detail_t *

本函数处理时,data为直接引用而非复制。

注意:变量必须有变量名。

返回值:成功则返回0,否则返回-1

mln_lang_func_detail_new

mln_lang_func_detail_t *mln_lang_func_detail_new(mln_lang_ctx_t *ctx, mln_lang_func_type_t type, void *data, mln_lang_exp_t *exp, mln_lang_exp_t *closure);

描述:创建函数定义。参数含义:

  • ctx脚本结构
  • type函数类型:内部函数(M_FUNC_INTERNAL) 和 脚本中定义的函数(M_FUNC_EXTERNAL
  • data函数的具体处理部分。typeM_FUNC_INTERNAL时,data类型为mln_lang_internal。否则类型为mln_lang_stm_t *,该类型为抽象语法树结构中的语句结构。
  • exp为参数列表表达式结构。对于使用C自行构造内部函数时,该参数置NULL,然后自行构造参数链表。

返回值:成功则返回函数定义结构指针,否则返回NULL

mln_lang_func_detail_free

void mln_lang_func_detail_free(mln_lang_func_detail_t *lfd);

描述:释放函数定义结构。

返回值:无

mln_lang_set_detail_new

mln_lang_set_detail_t *mln_lang_set_detail_new(mln_alloc_t *pool, mln_string_t *name);

描述:创建类(Set)定义结构。name不可为NULL,且本函数会对其完全拷贝一份。

返回值:成功则返回类定义结构指针,否则返回NULL

mln_lang_set_detail_free

void mln_lang_set_detail_free(mln_lang_set_detail_t *c);

描述:释放类定义结构。

返回值:无

mln_lang_set_detail_self_free

void mln_lang_set_detail_self_free(mln_lang_set_detail_t *c);

描述:释放类定义结构。与mln_lang_set_detail_free的差别在于,本函数会先释放类定义中的成员红黑树,而mln_lang_set_detail_free则是判断引用计数,若引用大于1则不会释放红黑树。

返回值:无

mln_lang_set_member_search

mln_lang_var_t *mln_lang_set_member_search(mln_rbtree_t *members, mln_string_t *name);

描述:查找成员红黑树中是否存在名为name的成员。本函数既可以用于类也可以用于对象的成员查询,因为两个结构都含有成员红黑树结构。

返回值:存在则返回成员的变量结构指针,则否返回NULL

mln_lang_set_member_add

int mln_lang_set_member_add(mln_alloc_t *pool, mln_rbtree_t *members, mln_lang_var_t *var);

描述:向类成员红黑树中增加一个成员var

返回值:成功则返回0,否则返回-1

mln_lang_object_add_member

int mln_lang_object_add_member(mln_lang_ctx_t *ctx, mln_lang_object_t *obj, mln_lang_var_t *var);

描述:向对象中增加一个成员var

返回值:成功则返回0,否则返回-1

mln_lang_array_new

 mln_lang_array_t *mln_lang_array_new(mln_lang_ctx_t *ctx);

描述:新建一个数组结构。

返回值:成功则返回数组结构指针,否则返回NULL

mln_lang_array_free

void mln_lang_array_free(mln_lang_array_t *array);

描述:释放数组结构,若数组引用计数大于1,则仅递减引用计数。

返回值:无

mln_lang_array_get

mln_lang_var_t *mln_lang_array_get(mln_lang_ctx_t *ctx, mln_lang_array_t *array, mln_lang_var_t *key);

描述:在数组array中获取下表为key的元素。若key不存在,则新建数组元素。若keyNULL,则自行追加数组下标。key为变量结构,即key既可以是整数,也可以是字符串,也可以是对象等等。

返回值:成功则返回新建元素或已存在元素的变量结构指针,否则返回NULL

mln_lang_array_elem_exist

int mln_lang_array_elem_exist(mln_lang_array_t *array, mln_lang_var_t *key);

描述:判断数组array中是否存在下标为key的元素。

返回值:存在则返回1,否则返回0

mln_lang_ctx_resource_register

int mln_lang_ctx_resource_register(mln_lang_ctx_t *ctx, char *name, void *data, mln_lang_resource_free free_handler);

typedef void (*mln_lang_resource_free)(void *data);

描述:向脚本任务ctx中注册脚本任务级别的资源及其清理函数。例如消息队列的消息需要在任务级别进行管理,例如当当前任务主动或者被动退出时,需要对该任务所使用到的资源进行统一清理。可参考Melon/melang/msgqueue中的使用。name为资源名称,data为资源指针,free_handler为释放函数,释放函数的参数即资源指针data

返回值:成功则返回0,否则返回-1

mln_lang_ctx_resource_fetch

void *mln_lang_ctx_resource_fetch(mln_lang_ctx_t *ctx, const char *name);

描述:获取脚本任务ctx中注册的名为name的资源。

返回值:若存在则返回资源指针,否则返回NULL

mln_lang_resource_register

int mln_lang_resource_register(mln_lang_t *lang, char *name, void *data, mln_lang_resource_free free_handler);

typedef void (*mln_lang_resource_free)(void *data);

描述:向脚本管理结构lang中注册名为name的资源data及其清理函数free_handler。这个注册的含义是,该资源将跨脚本任务被使用,例如网络通信时允许将套接字交由一个新协程单独处理。

返回值:成功则返回0,否则返回-1

mln_lang_resource_cancel

void mln_lang_resource_cancel(mln_lang_t *lang, const char *name);

描述:将名为name的资源从脚本管理结构中注销,并释放资源。

返回值:无

mln_lang_resource_fetch

void *mln_lang_resource_fetch(mln_lang_t *lang, const char *name);

描述:从脚本管理结构lang中获取名为name的资源结构。

返回值:若存在则返回资源指针,否则返回NULL

mln_lang_ctx_suspend

void mln_lang_ctx_suspend(mln_lang_ctx_t *ctx);

描述:将脚本任务ctx挂起等待。调用该函数前,必须要调用mln_lang_mutex_lock该宏上锁。

返回值:无

mln_lang_ctx_continue

void mln_lang_ctx_continue(mln_lang_ctx_t *ctx);

描述:将脚本任务ctx放回执行队列继续执行。调用该函数前,必须要调用mln_lang_mutex_lock该宏上锁。

返回值:无

mln_lang_func_detail_arg_append

void mln_lang_func_detail_arg_append(mln_lang_func_detail_t *func, mln_lang_var_t *var);

描述:将参数var挂入到函数定义func的参数列表最后方。

返回值:无

示例

函数的实现可以参考Melang/lib_src/aes中的内容,极为简洁。

类实现的部分可以参考Melang/lib_src/file中的内容。

results matching ""

    No results matching ""