Script development
This article will introduce how to develop a dynamic extension library for scripting languages, and also give various functions required for development.
Header file
#include "mln_lang.h"
Module
lang
Development steps
The development steps of dynamic extension library is as follows:
Construct a dynamic library with a function named
init
, where the function prototype ofinit
is:mln_lang_var_t *init(mln_lang_ctx_t *);
mln_lang_var_t
is the type of the return value of the function in the script task. For the creation method, please refer tomln_lang.h
and the implementation of various built-in functions of melang.Developers can load various script functions, collections, variables, etc. in the
init
function. If the function returnsnil
, this is similar to step 4 of the built-in library.The
mln_lang_var_t
return value ininit
is returned at the end of the functionimport
call.When using, call the
import
function in the script to import this dynamic library, and the program will call theinit
function to load the resources to be loaded in the library into the current scope of the script.
Functions/Macros
Developers can not only use the functions given here, but also the functions introduced in the previous article. For example, the implementation of the eval
function in Melang.
Structures
struct mln_lang_var_s {
mln_lang_ctx_t *ctx;//Script task structure
mln_lang_var_type_t type;//Is it a reference type
mln_string_t *name;//Variable name, anonymous variables will be set to NULL
mln_lang_val_t *val;//variable value structure
mln_lang_set_detail_t *in_set;//Whether it belongs to a Set structure (ie, class definition)
mln_lang_var_t *prev;
mln_lang_var_t *next;
mln_lang_var_t *prev;
mln_lang_var_t *next;
mln_uauto_t ref;//reference counter
};
struct mln_lang_val_s {
mln_lang_ctx_t *ctx;//Script task structure
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; //value data
mln_s32_t type;//data type
mln_u32_t ref;//The number of times the value structure is referenced
mln_lang_val_t *udata;//for reactive programming
mln_lang_func_detail_t *func;//for reactive programming
mln_u32_t not_modify:1;//read-only or not
};
struct mln_lang_symbol_node_s {
mln_string_t *symbol;//symbol string
mln_lang_ctx_t *ctx;//Script task structure
mln_lang_symbol_type_t type;//Symbol type: Class (M_LANG_SYMBOL_SET) or variable (M_LANG_SYMBOL_VAR)
union {
mln_lang_var_t *var;
mln_lang_set_detail_t *set;
} data;
mln_uauto_t layer;//The scope layer to which it belongs
mln_lang_hash_bucket_t *bucket;//Symbol table bucket structure
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;
};
In a script, these first two structures are the most important structures in the script. You can see that mln_lang_var_t
is a wrapper around mln_lang_val_t
. mln_lang_val_t
is used to store specific values, strings, etc. mln_lang_var_t
is generally used as a package structure for function parameters, return values, and array element values.
The reason for encapsulating a layer is for two aspects:
- Function parameters reference
- Mapping variable names to variable values
We can call the former a variable structure and the latter a value structure.
The types of value structures include the following:
M_LANG_VAL_TYPE_NIL
null valueM_LANG_VAL_TYPE_INT
integerM_LANG_VAL_TYPE_BOOL
booleanM_LANG_VAL_TYPE_REAL
realM_LANG_VAL_TYPE_STRING
stringM_LANG_VAL_TYPE_OBJECT
objectM_LANG_VAL_TYPE_FUNC
function definitionM_LANG_VAL_TYPE_ARRAY
arrayM_LANG_VAL_TYPE_CALL
function 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);
Description: Create a variable structure. The meanings of the parameters are as follows:
ctx
script structurename
variable name, orNULL
if nonetype
variable type, reference (M_LANG_VAR_REFER
) or copy (M_LANG_VAR_NORMAL
).- The value structure corresponding to
val
. - Whether
in_set
belongs to a Set (class definition), if not, setNULL
.
Return value: return the structure pointer if successful, otherwise return NULL
mln_lang_var_free
void mln_lang_var_free(void *data);
Description: Frees resources for pointer data
of type mln_lang_var_t
, including its internal value structure.
Return value: none
mln_lang_var_ref
mln_lang_var_ref(var)
Description: Creates a reference to the variable structure. During freeing, if the reference is greater than 1, the variable structure is not actually freed.
Return value: pointer of type mln_lang_var_t
mln_lang_var_val_get
mln_lang_var_val_get(var)
Description: Get the value structure of the pointer var
of type mln_lang_var_t
.
Return value: pointer of type mln_lang_val_t
mln_lang_val_not_modify_set
mln_lang_val_not_modify_set(val)
Description: Set the mln_lang_val_t
type pointer val
to be immutable.
Return value: none
mln_lang_val_not_modify_isset
mln_lang_val_not_modify_isset(val)
Description: Determine whether the pointer val
of type mln_lang_val_t
is immutable.
Return value: unchangeable returns non-0
, otherwise returns 0
mln_lang_val_not_modify_reset
mln_lang_val_not_modify_reset(val)
Description: Set the mln_lang_val_t
type pointer val
to be modifiable.
Return value: none
mln_lang_var_dup
mln_lang_var_t *mln_lang_var_dup(mln_lang_ctx_t *ctx, mln_lang_var_t *var);
Description: duplicate var
. For array and object type variables, only reference is not copied. The replica uses the memory pool structure in ctx for memory allocation.
Return value: variable structure pointer.
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);
Description: Assign the value in src
to dest
. If there is a value in dest
, the value will be released. For arrays and objects, only references, no copies. For strings, this function makes an exact copy.
Return value: return 0
if successful, otherwise return -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);
Description: Assign the value in src
to dest
. If there is a value in dest
, the value will be released. For arrays and objects, only references, no copies. For strings, this function only references and does not copy.
Return value: return 0
if successful, otherwise return -1
mln_lang_var_val_type_get
mln_s32_t mln_lang_var_val_type_get(mln_lang_var_t *var);
Description: Get the type of the value of the variable. For the type definition, see the relevant structure section.
Return value: type value
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);
Description: Add an outermost (also global) variable to the script task ctx
. The variable name is name
, the variable value is val
, and the type of the value is type
. type
satisfies the type defined in the relevant structure section. If it is a string type, the new variable will be referenced by mln_string_ref
, so pay attention to the possible problems caused when val
is allocated on the stack.
Return value: return 0
if successful, otherwise return -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);
Description: Creates a variable of type function call. This variable is only used in the script core and is mentioned here only by the way.
Return value: return the variable type pointer if successful, otherwise return NULL
mln_lang_var_create_nil
mln_lang_var_t *mln_lang_var_create_nil(mln_lang_ctx_t *ctx, mln_string_t *name);
Description: Creates a variable of empty type. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack.
Return value: return the variable type pointer if successful, otherwise return 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);
Description: Creates a variable of type object. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack. in_set
is the class (Set) to which the object belongs. This function only refers to in_set
without copying it completely.
Return value: return the variable type pointer if successful, otherwise return NULL
mln_lang_var_create_true
mln_lang_var_t *mln_lang_var_create_true(mln_lang_ctx_t *ctx, mln_string_t *name);
Description: Creates a boolean true variable. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack.
Return value: return the variable type pointer if successful, otherwise return NULL
mln_lang_var_create_false
mln_lang_var_t *mln_lang_var_create_false(mln_lang_ctx_t *ctx, mln_string_t *name);
Description: Creates a boolean false variable. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack.
Return value: return the variable type pointer if successful, otherwise return 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);
Description: Create a variable of integer type. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack.
Return value: return the variable type pointer if successful, otherwise return 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);
Description: Creates a variable of type real. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack.
Return value: return the variable type pointer if successful, otherwise return 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);
Description: Creates a boolean variable. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack. Boolean false when b
is 0
, boolean true otherwise.
Return value: return the variable type pointer if successful, otherwise return 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);
Description: Creates a variable of empty type. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack. This function makes an exact copy of s
.
Return value: return the variable type pointer if successful, otherwise return 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);
Description: Creates a variable of empty type. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack. This function will only refer to s
with mln_string_ref
, so pay attention to the effect of s
for stack allocated memory.
Return value: return the variable type pointer if successful, otherwise return NULL
mln_lang_var_create_array
mln_lang_var_t *mln_lang_var_create_array(mln_lang_ctx_t *ctx, mln_string_t *name);
Description: Creates an array type variable. If the variable does not require a variable name, name
is set to NULL
. Note that name will be referenced by mln_string_ref
, so you need to pay attention to the impact of name
for memory allocated on the stack. After creation, it is an empty array.
Return value: return the variable type pointer if successful, otherwise return NULL
mln_lang_condition_is_true
int mln_lang_condition_is_true(mln_lang_var_t *var);
escription: Determines whether the value of the var
variable is logically true.
Return value: 1
if true, 0
otherwise
mln_lang_ctx_set_ret_var
void mln_lang_ctx_set_ret_var(mln_lang_ctx_t *ctx, mln_lang_var_t *var);
Description: Set the return value of the current script task ctx
to var
. var
is referenced here rather than copied.
Return value: none
mln_lang_val_new
mln_lang_val_t *mln_lang_val_new(mln_lang_ctx_t *ctx, mln_s32_t type, void *data);
Description: Create a value structure. See the relevant structure section for the type
type. data
is different according to type
, so its type is also different. For the specific type, please refer to the type of the community part of the structure in the related structure. But it should be noted that this parameter is a pointer type, that is, the integer type is mln_s64_t *
rather than mln_s64_t
type cast.
Return value: return value structure pointer if successful, otherwise return NULL
mln_lang_val_free
void mln_lang_val_free(mln_lang_val_t *val);
Description: Frees the value structure.
Return value: none
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);
Description: Query the symbol table of script task ctx
for the symbol named name
. local
is non-0
if the query is only made within the current function scope, 0
otherwise.
Return value: Returns the symbolic structure pointer if it exists, otherwise returns 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);
Description: Add data
of type type
to the symbol table. The value of type
is:
M_LANG_SYMBOL_VAR
- variableM_LANG_SYMBOL_SET
- class
Depending on the type
, the type of data
is different:
mln_lang_var_t*
mln_lang_set_detail_t *
When processed by this function, data
is referenced directly and not copied.
Note: Variables must have variable names.
Return value: return 0
if successful, otherwise return -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);
Description: Add data
of type type
to the symbol table of the previous scope. If it is already the outermost layer, add it to the outermost symbol table. The value of type
is:
M_LANG_SYMBOL_VAR
- variableM_LANG_SYMBOL_SET
- class
Depending on the type
, the type of data
is different:
mln_lang_var_t*
mln_lang_set_detail_t *
When processed by this function, data
is referenced directly and not copied.
Note: Variables must have variable names.
Return value: return 0
if successful, otherwise return -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);
Description: Create a function definition. Parameter meaning:
ctx
script structuretype
function type: internal functions (M_FUNC_INTERNAL
) and functions defined in scripts (M_FUNC_EXTERNAL
)- The specific processing part of the
data
function. Whentype
isM_FUNC_INTERNAL
,data
type ismln_lang_internal
. Otherwise the type ismln_lang_stm_t *
, which is the statement structure in the abstract syntax tree structure. exp
is a parameter list expression structure. When using C to construct the internal function by yourself, set this parameter toNULL
, and then construct the parameter list by yourself.
Return value: If successful, return the function definition structure pointer, otherwise return NULL
mln_lang_func_detail_free
void mln_lang_func_detail_free(mln_lang_func_detail_t *lfd);
Description: Free the function definition structure.
Return value: none
mln_lang_set_detail_new
mln_lang_set_detail_t *mln_lang_set_detail_new(mln_alloc_t *pool, mln_string_t *name);
Description: Create a class (Set) definition structure. name
cannot be NULL
, and this function will make a full copy of it.
Return value: If successful, return the class definition structure pointer, otherwise return NULL
mln_lang_set_detail_free
void mln_lang_set_detail_free(mln_lang_set_detail_t *c);
Description: Frees the class definition structure.
Return value: none
mln_lang_set_detail_self_free
void mln_lang_set_detail_self_free(mln_lang_set_detail_t *c);
Description: Frees the class definition structure. The difference from mln_lang_set_detail_free
is that this function will first release the member red-black tree in the class definition, while mln_lang_set_detail_free
is to judge the reference count, if the reference is greater than 1, the red-black tree will not be released.
Return value: none
mln_lang_set_member_search
mln_lang_var_t *mln_lang_set_member_search(mln_rbtree_t *members, mln_string_t *name);
Description: Finds if a member named name
exists in a member red-black tree. This function can be used for both class and object member query, because both structures contain member red-black tree structures.
Return value: if it exists, return the variable structure pointer of the member, otherwise return 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);
Description: Add a member var
to the red-black tree of class members.
Return value: return 0
if successful, otherwise return -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);
Description: Add a member var
to the object.
Return value: return 0
if successful, otherwise return -1
mln_lang_array_new
mln_lang_array_t *mln_lang_array_new(mln_lang_ctx_t *ctx);
Description: Create a new array structure.
Return value: return array structure pointer if successful, otherwise return NULL
mln_lang_array_free
void mln_lang_array_free(mln_lang_array_t *array);
Description: Free the array structure, if the array reference count is greater than 1, only decrement the reference count.
Return value: none
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);
Description: Get the element of key
in the following table in the array array
. If key
does not exist, create a new array element. If key
is NULL
, the array subscript will be appended by itself. key
is a variable structure, that is, key
can be either an integer, a string, an object, etc.
Return value: If successful, return the variable structure pointer of the new element or the existing element, otherwise return NULL
mln_lang_array_elem_exist
int mln_lang_array_elem_exist(mln_lang_array_t *array, mln_lang_var_t *key);
Description: Determines whether the element with subscript key
exists in the array array
.
Return value: returns 1
if exists, otherwise returns 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);
Description: Register script task level resources and their cleanup functions with script task ctx
. For example, the messages of the message queue need to be managed at the task level. For example, when the current task exits actively or passively, the resources used by the task need to be cleaned up uniformly. See the usage in Melon/melang/msgqueue
. name
is the resource name, data
is the resource pointer, free_handler
is the release function, and the parameter of the release function is the resource pointer data
.
Return value: return 0
if successful, otherwise return -1
mln_lang_ctx_resource_fetch
void *mln_lang_ctx_resource_fetch(mln_lang_ctx_t *ctx, const char *name);
Description: Get the resource named name
registered in the script task ctx
.
Return value: Returns the resource pointer if it exists, otherwise returns 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);
Description: Register a resource data
named name
and its cleanup function free_handler
with the script management structure lang
. The meaning of this registration is that the resource will be used across scripting tasks, such as network communication, allowing the socket to be handled by a new coroutine alone.
Return value: return 0
if successful, otherwise return -1
mln_lang_resource_cancel
void mln_lang_resource_cancel(mln_lang_t *lang, const char *name);
Description: Unregister the resource named name
from the script management structure and free the resource.
Return value: none
mln_lang_resource_fetch
void *mln_lang_resource_fetch(mln_lang_t *lang, const char *name);
Description: Get a resource structure named name
from the script management structure lang
.
Return value: Returns the resource pointer if it exists, otherwise returns NULL
mln_lang_ctx_suspend
void mln_lang_ctx_suspend(mln_lang_ctx_t *ctx);
Description: Suspend script task ctx
to wait. mln_lang_mutex_lock
must be called before calling this function.
Return value: none
mln_lang_ctx_continue
void mln_lang_ctx_continue(mln_lang_ctx_t *ctx);
Description: Put the script task ctx
back in the execution queue to continue execution. mln_lang_mutex_lock
must be called before calling this function.
Return value: none
mln_lang_func_detail_arg_append
void mln_lang_func_detail_arg_append(mln_lang_func_detail_t *func, mln_lang_var_t *var);
Description: Append argument var
to the argument list of function definition func
.
Return value: none
示例
The implementation of the function can refer to the content in Melang/lib_src/aes
, which is extremely concise.
The part of the class implementation can refer to the content in Melang/lib_src/file
.