quickjs C功能扩展的四种写法

一、前言

   茴香豆的“茴”字有多少种写法?这篇博客不是为了炫技,是JS就是这么多种情况。比如C语言,就只能通过函数调用,没有类的概念。比如Java,就只能通过类、对象的方式。不能单独创建函数。哪怕main函数也要包装成一个class。而JS,即可以提供函数,也可以提供类。

  在ES5之前,JS还没有模块的概念,现在用的quickjs已经支持模块引用。我看其他人用JerryScript之类的,虽然不支持模块引用,但是可以通过Babel、tsc之类的,解决低版本js引擎对新语法的支持。

二、以完整模块导出函数、属性

  绑定

 1 static JSValue JLJS_Print(JSContext *ctx, JSValueConst this_val,
 2                               int argc, JSValueConst *argv)
 3 {
 4   const char *str;
 5   if(argc > 0){
 6     str = JS_ToCString(ctx, argv[0]);
 7   }
 8   printf("->%s\n", str);
 9   JS_FreeCString(ctx, str);
10 }
11 static const JSCFunctionListEntry jl_js_print_funcs[] = {
12     JS_CFUNC_DEF("Print", 1, JLJS_Print)
13 };
14 static int jl_js_print_init(JSContext *ctx, JSModuleDef *m)
15 {
16   return JS_SetModuleExportList(ctx, m, jl_js_print_funcs, countof(jl_js_print_funcs));
17 }
18 JSModuleDef* jl_js_init_module_print(JSContext *ctx, const char *module_name)
19 {
20   JSModuleDef * m = JS_NewCModule(ctx, module_name, jl_js_print_init);
21   if(!m)
22   {
23     return NULL;
24   }
25   JS_AddModuleExportList(ctx, m, jl_js_print_funcs, countof(jl_js_print_funcs));
26   return m;
27 }

  注册

1 jl_js_init_module_print(qrt->ctx, "m");

  调用

1 import * as m from 'm';
2 m.Print('hello world');
3 
4 import {Print} from 'm';
5 Print('hello world');

 

三、以属性形式导出函数、属性

  绑定

1 static const JSCFunctionListEntry jl_js_m_print_funcs[] = {
2     JS_OBJECT_DEF("m", jl_js_print_funcs, countof(jl_js_print_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)
3 };
4 void jl_js_init_register(JSContext* ctx, JSValue global)
5 {
6   JSValue obj = JS_NewObjectProto(ctx, JS_NULL);
7   JS_SetPropertyFunctionList(ctx, obj, jl_js_m_print_funcs, countof(jl_js_m_print_funcs));
8   JS_DefinePropertyValueStr(ctx, global, "reg", obj, JS_PROP_C_W_E);
9 }

  注册

1 JSValue global_obj = JS_GetGlobalObject(qrt->ctx);
2 jl_js_init_register(qrt->ctx, global_obj);

  调用

1 reg.m.Print('reg.m.Print');

 

四、以完整模块导出类、对象

  绑定

 1 typedef struct{
 2   int val;
 3 } PrintClass;
 4 static JSClassID print_class_id;
 5 static void JLJS_CLASS_PrintFinalize(JSRuntime *rt, JSValue val)
 6 {
 7   PrintClass *cls = (PrintClass *)JS_GetOpaque(val, print_class_id);
 8   if(cls){
 9     js_free_rt(rt, cls);
10   }
11 }
12 static JSClassDef print_class_def = {
13   .class_name = "Print",
14   .finalizer = JLJS_CLASS_PrintFinalize, // 析构函数
15   .gc_mark = NULL
16 };
17 //构造函数
18 static JSValue JLJS_CLASS_PrintConstructor(JSContext *ctx, JSValueConst new_target,
19                                        int argc, JSValueConst *argv)
20 {
21   JSValue obj = JS_UNDEFINED;
22   PrintClass *cls = (PrintClass *)js_malloc(ctx, sizeof(PrintClass));
23   if(argc > 0){
24     JS_ToInt32(ctx, &cls->val, argv[0]);
25     JSValue val = JS_DupValue(ctx, argv[0]);
26   }
27   JSValue proto = JS_GetPropertyStr(ctx, new_target, "prototype");
28   obj = JS_NewObjectProtoClass(ctx, JS_NULL/*proto*/, print_class_id);
29   JS_SetPrototype(ctx, obj, proto);
30   JS_FreeValue(ctx, proto);
31   JS_SetOpaque(obj, cls);
32   return obj;
33 }
34 static JSValue JLJS_CLASS_PrintTestFunc(JSContext *ctx, JSValueConst this_val,
35                                        int argc, JSValueConst *argv)
36 {
37   PrintClass * cls = (PrintClass *) JS_GetOpaque2(ctx, this_val, print_class_id);
38   if(cls == NULL){
39     return JS_EXCEPTION;
40   }
41   if(argc > 0){
42     JS_ToInt32(ctx, &cls->val, argv[0]);
43   }
44   printf("Print Value: %d\n", cls->val);
45 }
46 static JSValue jl_js_print_class_get_val(JSContext *ctx, JSValueConst this_val)
47 {
48   PrintClass * cls = (PrintClass *) JS_GetOpaque2(ctx, this_val, print_class_id);
49   if(cls == NULL){
50     return JS_EXCEPTION;
51   }
52   return JS_NewInt32(ctx, cls->val);
53 }
54 static JSValue jl_js_print_class_set_val(JSContext *ctx, JSValueConst this_val, JSValueConst val)
55 {
56   PrintClass * cls = (PrintClass *) JS_GetOpaque2(ctx, this_val, print_class_id);
57   if(cls == NULL){
58     return JS_EXCEPTION;
59   }
60   JS_ToInt32(ctx, &cls->val, val);
61   return JS_UNDEFINED;
62 }
63 static const JSCFunctionListEntry jl_js_print_class_funcs[] = {
64     JS_CFUNC_DEF("PrintTestFunc", 1, JLJS_CLASS_PrintTestFunc),
65     // JS_PROP_INT32_DEF("val", 1, JS_PROP_C_W_E)
66     JS_CGETSET_DEF("val", jl_js_print_class_get_val, jl_js_print_class_set_val)
67 };
68 void jl_js_init_print_class_module(JSContext* ctx, JSModuleDef *m)
69 {
70   JS_NewClassID(&print_class_id);
71   JS_NewClass(JS_GetRuntime(ctx), print_class_id, &print_class_def);
72   JSValue proto = JS_NewObject(ctx);
73   JS_SetPropertyFunctionList(ctx, proto, jl_js_print_class_funcs, countof(jl_js_print_class_funcs));
74 
75   JSValue ctor = JS_NewCFunction2(ctx, JLJS_CLASS_PrintConstructor, print_class_def.class_name, 1, JS_CFUNC_constructor, 0);
76   JS_SetConstructor(ctx, ctor, proto); //给proto设置一个构造函数ctor
77   JS_SetClassProto(ctx, print_class_id, proto); //为print这个类,设置原型链
78   JS_SetModuleExport(ctx, m, print_class_def.class_name, ctor);//设置可导出类 只导出构造函数
79 }
80 int jl_js_init_class_module_list(JSContext *ctx, JSModuleDef *m)
81 {
82   jl_js_init_print_class_module(ctx, m);
83   //其他class初始化
84   return 0;
85 }
86 JSModuleDef* jl_js_init_class_module(JSContext *ctx, const char *module_name)
87 {
88   JSModuleDef * m = JS_NewCModule(ctx, module_name, jl_js_init_class_module_list);
89   if(!m)
90   {
91     return NULL;
92   }
93   //导出类名,注意这里与上面的JS_SetModuleExport对应
94   JS_AddModuleExport(ctx, m, print_class_def.class_name);
95   return m;
96 }

  注册

1 jl_js_init_class_module(qrt->ctx, "_G");

  调用

 1 import * as _G from '_G'
 2 var g = new _G.Print(1);
 3 g.val = 3;
 4 g.PrintTestFunc();
 5 g.PrintTestFunc(10);
 6 
 7 import {Print} from '_G';
 8 var g = new Print(1);
 9 g.val = 3;
10 g.PrintTestFunc();
11 g.PrintTestFunc(10);

 

五、以属性形式导出类、对象

  绑定

 1 void jl_js_init_class_register(JSContext *ctx, JSValue global)
 2 {
 3   JS_NewClassID(&print_class_id);
 4   JS_NewClass(JS_GetRuntime(ctx), print_class_id, &print_class_def);
 5   JSValue proto = JS_NewObjectProto(ctx, JS_NULL);
 6   JS_SetPropertyFunctionList(ctx, proto, jl_js_print_class_funcs, countof(jl_js_print_class_funcs));
 7 
 8   JSValue ctor = JS_NewCFunction2(ctx, JLJS_CLASS_PrintConstructor, print_class_def.class_name, 1, JS_CFUNC_constructor, 0);
 9   JS_SetConstructor(ctx, ctor, proto); //给proto设置一个构造函数ctor
10   JS_SetClassProto(ctx, print_class_id, proto); //为print这个类,设置原型链
11 
12   JS_DefinePropertyValueStr(ctx, global, "Print", ctor, JS_PROP_C_W_E);
13 }

  注册

1 jl_js_init_class_register(qrt->ctx, global_obj);

  调用 

1 var pt = new Print(1);
2 pt.val = 3;
3 pt.PrintTestFunc();

 

六、JS_EVAL_FLAG说明

1 #define JS_EVAL_FLAG_STRICT   (1 << 3)              //10XX,表示force 'strict' mode
2 #define JS_EVAL_FLAG_STRIP    (1 << 4)              //100XX,表示force 'strip' mode
3 #define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)           //1000XX,表示编译但不运行,结果是an object with a JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag.可以通过JS_EvalFunction()执行。
4 /*  in the Error() backtraces */
5 #define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)      //10000xx,表示在Error()回溯过程中don't include the stack frames before this eval

  执行JS_Eval函数时,如果传入的是 JS_EVAL_TYPE_MODULE| JS_EVAL_FLAG_COMPILE_ONLY  则 JS_Eval返回JS_TAG_MODULE。如果传入的是 JS_EVAL_TYPE_GLOBAL| JS_EVAL_FLAG_COMPILE_ONLY 返回JS_TAG_FUNCTION_BYTECODE。

 

 

本文地址:https://www.cnblogs.com/wunaozai/p/17901642.html

系列目录:https://www.cnblogs.com/wunaozai/p/17853962.html

posted @ 2023-12-14 19:28  无脑仔的小明  阅读(393)  评论(0编辑  收藏  举报