首页 > 其他分享 >quickjs模块封装、类封装

quickjs模块封装、类封装

时间:2023-12-05 14:58:09浏览次数:30  
标签:quickjs 封装 name val button ctx JS 模块 class

一、模块封装、类封装

  通过quickjs,封装JS模块,然后可以通过import 导入对应模块,还可以导入具体的类。全部代码如下。

  1 #include "quickjs-libc.h"
  2 #include <stdio.h>
  3 #include <inttypes.h>
  4 #include <string.h>
  5 #include "cutils.h"
  6 
  7 static JSClassID button_class_id;
  8 typedef struct _button
  9 {
 10   int val;
 11   const char *name;
 12   int serid;
 13 }Button;
 14 static JSValue JSButtonCreate(JSContext *ctx, JSValueConst val, int argc, JSValueConst *argv)
 15 {
 16   JSValue obj = JS_UNDEFINED;
 17   Button * button = (Button*)js_malloc(ctx, sizeof(Button));
 18   if(argc > 1){
 19     JS_ToInt32(ctx, &button->val, argv[0]);
 20     button->name = JS_ToCString(ctx, argv[1]);
 21   }else if(argc > 0){
 22     JS_ToInt32(ctx, &button->val, argv[0]);
 23   }
 24   JSValue proto = JS_GetPropertyStr(ctx, val, "prototype");
 25   obj = JS_NewObjectProtoClass(ctx, JS_NULL, button_class_id);
 26   JS_SetPrototype(ctx, obj, proto);
 27   JS_FreeValue(ctx, proto);
 28   JS_SetOpaque(obj, button);
 29   return obj;
 30 }
 31 static void JSButtonFinalizer(JSRuntime *rt, JSValue val)
 32 {
 33   Button *button = (Button *)JS_GetOpaque(val, button_class_id);
 34   if(button){
 35     printf("\nfinalizer!\n");
 36   }
 37 }
 38 
 39 static JSClassDef button_class_def = {
 40   .class_name = "Button",
 41   .finalizer = JSButtonFinalizer,
 42 };
 43 static JSValue JSButtonGetVal(JSContext *ctx, JSValueConst this_val)
 44 {
 45   Button * button = (Button*)JS_GetOpaque2(ctx, this_val, button_class_id);
 46   if(button == NULL){
 47     return JS_EXCEPTION;
 48   }
 49   return JS_NewInt32(ctx, button->val);
 50 }
 51 static JSValue JSButtonSetVal(JSContext *ctx, JSValueConst this_val, JSValueConst val)
 52 {
 53   Button * button = (Button*)JS_GetOpaque2(ctx, this_val, button_class_id);
 54   if(button == NULL){
 55     return JS_EXCEPTION;
 56   }
 57   int v = 0;
 58   JS_ToInt32(ctx, &v, val);
 59   button->val = v;
 60   return JS_UNDEFINED;
 61 }
 62 static JSValue JSButtonGetName(JSContext *ctx, JSValueConst this_val)
 63 {
 64   Button * button = (Button*)JS_GetOpaque2(ctx, this_val, button_class_id);
 65   if(button == NULL){
 66     return JS_EXCEPTION;
 67   }
 68   return JS_NewString(ctx, button->name);
 69 }
 70 static JSValue JSButtonSetName(JSContext *ctx, JSValueConst this_val, JSValueConst val)
 71 {
 72   Button * button = (Button*)JS_GetOpaque2(ctx, this_val, button_class_id);
 73   if(button == NULL){
 74     return JS_EXCEPTION;
 75   }
 76   button->name = JS_ToCString(ctx, val);
 77   return JS_UNDEFINED;
 78 }
 79 static JSValue JSButtonTestFunc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
 80 {
 81   Button * button = (Button*)JS_GetOpaque2(ctx, this_val, button_class_id);
 82   if(button == NULL){
 83     return JS_EXCEPTION;
 84   }
 85   if(argc > 0){
 86     button->name = JS_ToCString(ctx, argv[0]);
 87   }
 88   printf("test function1 called: argv=%s serid=%d\n", button->name, button->serid);
 89 }
 90 static JSValue JSButtonTestFunc2(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
 91 {
 92   printf("test function 22 called\n");
 93 }
 94 
 95 static const JSCFunctionListEntry button_class_funcs[] = {
 96   JS_CFUNC_DEF("testFunc", 0, JSButtonTestFunc),
 97   JS_PROP_INT32_DEF("serid", 1, JS_PROP_C_W_E),
 98   JS_CGETSET_DEF("name", JSButtonGetName, JSButtonSetName),
 99   JS_CGETSET_DEF("val", JSButtonGetVal, JSButtonSetVal)
100 };
101 static const JSCFunctionListEntry button_only_funcs[] = {
102   JS_CFUNC_DEF("testFunc2", 0, JSButtonTestFunc2),
103 };
104 
105 void ButtonClassInit(JSContext *ctx, JSModuleDef *m)
106 {
107   JS_NewClassID(&button_class_id);
108   JS_NewClass(JS_GetRuntime(ctx), button_class_id, &button_class_def);
109 
110   JSValue proto = JS_NewObject(ctx);
111   JS_SetPropertyFunctionList(ctx, proto, button_class_funcs, countof(button_class_funcs));  
112   
113   JSValue class = JS_NewCFunction2(ctx, JSButtonCreate, button_class_def.class_name, 1, JS_CFUNC_constructor, 0);
114   JS_SetConstructor(ctx, class, proto);
115   JS_SetClassProto(ctx, button_class_id, proto);
116   JS_SetModuleExport(ctx, m, button_class_def.class_name, class); //设置可导出类
117   JS_SetModuleExportList(ctx, m, button_only_funcs, countof(button_only_funcs)); //设置可导出函数
118 }
119 
120 int GuiModuleInit(JSContext *ctx, JSModuleDef *m)
121 {
122   ButtonClassInit(ctx, m);
123   //其他class初始化
124   return 0;
125 }
126 
127 int TestExportClassToJavaScript(JSContext *ctx)
128 {
129   JSModuleDef *m = JS_NewCModule(ctx, "Gui", GuiModuleInit);
130   if (!m)
131     return -1;
132 
133   JS_AddModuleExport(ctx, m, button_class_def.class_name); //导出类名
134   JS_AddModuleExport(ctx, m, "testFunc2"); //导出函数名
135 
136   char script[] = R"(
137     import {Button, testFunc2} from 'Gui';
138     import * as std from 'std';
139     std.printf("HELLO\n");
140     var tmp = new Button(1, "HI");
141     std.printf("val:" + tmp.val + " name:" + tmp.name + " serid:" + tmp.serid + "\n");
142     tmp.val = 123;
143     tmp.name = "WNZ";
144     tmp.serid = 123456789;
145     std.printf(tmp.val + "\n")
146     std.printf(tmp.name + "\n")
147     std.printf(tmp.serid + "\n")
148     tmp.cc = 111
149     std.printf(JSON.stringify(tmp) + "\n");
150     tmp.testFunc("a")
151     testFunc2()
152   )";
153   
154   JS_Eval(ctx, script, strlen(script), "<test>", JS_EVAL_TYPE_MODULE);
155   return 0;
156 }
157 
158 int main(int argc, char **argv)
159 {
160   JSRuntime *rt = JS_NewRuntime();
161   js_std_init_handlers(rt);;
162   JSContext *ctx = JS_NewContext(rt);
163   JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
164   js_std_add_helpers(ctx, -1, NULL);
165   js_init_module_os(ctx, "os");
166   js_init_module_std(ctx, "std");
167 
168   TestExportClassToJavaScript(ctx);
169   js_std_dump_error(ctx);
170   JS_FreeContext(ctx);
171   JS_FreeRuntime(rt);
172   return 0;
173 }

 

二、运行打印

 1 PS D:\test\quickjs\examples\byte> gcc .\main.c .\libquickjs.a  -I ..\..\ -o main ; .\main
 2 HELLO
 3 val:1 name:HI serid:1
 4 123
 5 WNZ
 6 123456789
 7 {"serid":123456789,"cc":111}
 8 test function1 called: argv=a serid=0
 9 test function 22 called
10 
11 finalizer!
12 null

 

三、代码简单讲解

  定义一个全局唯一的类ID(JSClassID)、js所需的类定义(JSClassDef)、类属性

 1 static JSClassID button_class_id;
 2 typedef struct _button
 3 {
 4   int val;
 5   const char *name;
 6   int serid;
 7 }Button;
 8 static JSClassDef button_class_def = {
 9   .class_name = "Button",
10   .finalizer = JSButtonFinalizer,
11 };

  定义类的构造函数、析构函数。注意、这里的finalizer析构函数,需要在定义button_class_def时就指定,不能在后面再指定,否则不执行。

 1 static JSValue JSButtonCreate(JSContext *ctx, JSValueConst val, int argc, JSValueConst *argv)
 2 {
 3   JSValue obj = JS_UNDEFINED;
 4   Button * button = (Button*)js_malloc(ctx, sizeof(Button));
 5   if(argc > 1){
 6     JS_ToInt32(ctx, &button->val, argv[0]);
 7     button->name = JS_ToCString(ctx, argv[1]);
 8   }else if(argc > 0){
 9     JS_ToInt32(ctx, &button->val, argv[0]);
10   }
11   JSValue proto = JS_GetPropertyStr(ctx, val, "prototype");
12   obj = JS_NewObjectProtoClass(ctx, JS_NULL, button_class_id);
13   JS_SetPrototype(ctx, obj, proto);
14   JS_FreeValue(ctx, proto);
15   JS_SetOpaque(obj, button);
16   return obj;
17 }
18 static void JSButtonFinalizer(JSRuntime *rt, JSValue val)
19 {
20   Button *button = (Button *)JS_GetOpaque(val, button_class_id);
21   if(button){
22     printf("\nfinalizer!\n");
23   }
24 }

  属性的两种定义方式、普通的属性JS_DEF_PROP_INT32、具有getset的属性JS_DEF_CGETSET。

  属性的绑定,还有类的创建和导出,这一部分会进行简写,使用框架自带的宏

 1 int ButtonClassInit(JSContext *ctx, JSModuleDef *m)
 2 {
 3   JS_NewClassID(&button_class_id);
 4   JS_NewClass(JS_GetRuntime(ctx), button_class_id, &button_class_def);
 5 
 6   JSValue proto = JS_NewObject(ctx);
 7   JSCFunctionListEntry entryList[3];
 8   entryList[0].name = "val";
 9   entryList[0].prop_flags = JS_PROP_CONFIGURABLE;
10   entryList[0].def_type = JS_DEF_CGETSET;
11   entryList[0].magic = 0;
12   entryList[0].u.getset.get.getter = JSButtonGetVal;
13   entryList[0].u.getset.set.setter = JSButtonSetVal;
14   entryList[1].name = "name";
15   entryList[1].prop_flags = JS_PROP_CONFIGURABLE;
16   entryList[1].def_type = JS_DEF_CGETSET;
17   entryList[1].magic = 0;
18   entryList[1].u.getset.get.getter = JSButtonGetName;
19   entryList[1].u.getset.set.setter = JSButtonSetName;
20   entryList[2].name = "serid";
21   entryList[2].prop_flags = JS_PROP_C_W_E;
22   entryList[2].def_type = JS_DEF_PROP_INT32;
23   entryList[2].magic = 0;
24   entryList[2].u.i32 = 999;
25   // button_class_def.finalizer = JSButtonFinalizer; //析构函数
26   JS_SetPropertyFunctionList(ctx, proto, entryList, 3);
27   JSValue class = JS_NewCFunction2(ctx, JSButtonCreate, button_class_def.class_name, 1, JS_CFUNC_constructor, 0);
28   JS_SetConstructor(ctx, class, proto);
29   JS_SetClassProto(ctx, button_class_id, proto);
30   JS_SetModuleExport(ctx, m, button_class_def.class_name, class);
31 }

  JS测试代码、 可以通过import{Button} from 'Gui' 导出某个模块中具体的类。如果是函数,可以通过 import {testFunc2} from 'Gui' 导出某个模块中的具体函数。还可以通过 import * as gui from 'Gui' 导出整个模块。

 1 int TestExportClassToJavaScript(JSContext *ctx)
 2 {
 3   JSModuleDef *m = JS_NewCModule(ctx, "Gui", GuiModuleInit);
 4   if (!m)
 5     return -1;
 6 
 7   JS_AddModuleExport(ctx, m, button_class_def.class_name);
 8 
 9   char script[] = R"(
10     import {Button} from 'Gui';
11     import * as std from 'std';
12     std.printf("HELLO\n");
13     var tmp = new Button(1, "HI");
14     std.printf("val:" + tmp.val + " name:" + tmp.name + " serid:" + tmp.serid + "\n");
15     tmp.val = 123;
16     tmp.name = "WNZ";
17     tmp.serid = 123456789;
18     std.printf(tmp.val + "\n")
19     std.printf(tmp.name + "\n")
20     std.printf(tmp.serid + "\n")
21     tmp.cc = 111
22     std.printf(JSON.stringify(tmp));
23   )";
24   
25   JS_Eval(ctx, script, strlen(script), "<test>", JS_EVAL_TYPE_MODULE);
26   return 0;
27 }

四、类的函数定义

  上面讲的是属性的定义、下面这个是函数的定义,方法其实跟之前博文中类似,只是之前是通过一个宏 JS_CFUNC_DEF 进行定义和绑定的。简写后如下

 1 static const JSCFunctionListEntry button_class_funcs[] = {
 2   JS_CFUNC_DEF("testFunc", 0, JSButtonTestFunc),
 3   JS_PROP_INT32_DEF("serid", 1, JS_PROP_C_W_E),
 4   JS_CGETSET_DEF("name", JSButtonGetName, JSButtonSetName),
 5   JS_CGETSET_DEF("val", JSButtonGetVal, JSButtonSetVal)
 6 };
 7 static const JSCFunctionListEntry button_only_funcs[] = {
 8   JS_CFUNC_DEF("testFunc2", 0, JSButtonTestFunc2),
 9 };
10 
11 void ButtonClassInit(JSContext *ctx, JSModuleDef *m)
12 {
13   JS_NewClassID(&button_class_id);
14   JS_NewClass(JS_GetRuntime(ctx), button_class_id, &button_class_def);
15 
16   JSValue proto = JS_NewObject(ctx);
17   JS_SetPropertyFunctionList(ctx, proto, button_class_funcs, countof(button_class_funcs));  
18   
19   JSValue class = JS_NewCFunction2(ctx, JSButtonCreate, button_class_def.class_name, 1, JS_CFUNC_constructor, 0);
20   JS_SetConstructor(ctx, class, proto);
21   JS_SetClassProto(ctx, button_class_id, proto);
22   JS_SetModuleExport(ctx, m, button_class_def.class_name, class); //设置可导出类
23   JS_SetModuleExportList(ctx, m, button_only_funcs, countof(button_only_funcs)); //设置可导出函数
24 }

 

 

 

参考资料:

  https://www.cnblogs.com/rpg3d/p/17278800.html

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

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

标签:quickjs,封装,name,val,button,ctx,JS,模块,class
From: https://www.cnblogs.com/wunaozai/p/17862838.html

相关文章

  • SIM800C模块(2G)连接千寻
    1.测试//ATK-SIM900A各项测试(拨号测试、短信测试、GPRS测试)共用代码//sim900a发送命令后,检测接收到的应答//str:期待的应答结果//返回值:0,没有得到期待的应答结果//其他,期待应答结果的位置(str的位置)uint8_t*sim900a_check_cmd(uint8_t*str){char*str......
  • 硬件开发笔记(十四):RK3568底板电路LVDS模块、MIPI模块电路分析、LVDS硬件接口、MIPI硬件
    前言  本篇继续分析底板原理图mipi/lvds屏幕电路原理图、硬件接口详解。 LVDS与MIPI的区别  液晶屏有RGBTTL、LVDS、MIPI、HDMI接口,这些接口区别于信号的类型(种类),也区别于信号内容。RGBTTL接口信号类型是TTL电平,信号的内容是RGB666或者RGB888还有行场同步和......
  • Ansible自动化运维模块详解
    ansible ad-hoc点对点模块l ping模块主机连通性测试[root@node2~]#ansibleall-mping192.168.200.10|SUCCESS=>{    "ansible_facts":{        "discovered_interpreter_python":"/usr/bin/python"    },    "changed":fals......
  • 微信小程序 wx.request Typescript 封装统一请求
    话不多说直接上代码,想懂的终究会懂,哈哈哈哈文件名:request.ts 1/**2*HttpMethod类型api处要用3*/4exportenumHttpMethod{5Get="GET",6Post="POST",7Options="OPTIONS",8Put="PUT",9Delete=......
  • 4.1 配置Mysql与注册登录模块(上)
    点击查看sql代码createdatabasekob;usekob;createtableuser(idint,usernamevarchar(100),passwordvarchar(100));mysql>showtables;+---------------+|Tables_in_kob|+---------------+|user|+---------------+1rowinset(0.00sec)......
  • quickjs加载字节码文件
    一、使用qjsc编译字节码hello.js console.log("HelloWorld") qjsc.exe-chello.js1constuint32_tqjsc_hello_size=78;23constuint8_tqjsc_hello[78]={40x02,0x04,0x0e,0x63,0x6f,0x6e,0x73,0x6f,50x6c,0x65,0x06,0x6c,0x6f,......
  • stack和queue的底层容器封装 以及提供随机存储的容器
    在C++中,std::stack和std::queue是容器适配器,它们提供了特定的接口,依赖于某个容器类(如std::deque或std::list)来处理元素1。std::stack:std::stack默认使用std::deque作为其底层容器2。但是,你也可以在创建std::stack对象时指定其他的底层容器,只要这个容器支持......
  • 振弦读数模块开发时的要点
    振弦读数模块开发时的要点振弦读数模块是振弦采集仪中重要的组成部分,以下是开发时需要注意的要点: 1.确定采样频率和精度:振弦采集仪必须以足够高的频率和精度采集振弦信号,以确保数据的准确性和完整性。2.选择合适的传感器:振弦读数模块需要与振弦传感器配合使用,传感器的品质......
  • 常见的DC电源模块故障排除方法?
    BOSHIDA常见的DC电源模块故障排除方法?以下是常见的DC电源模块故障排除方法: 1.检查电源输入电压是否正确,是否在规定范围内。2.检查输出电压是否正确,是否符合规定的值。3.检查电源输出端是否正常,是否有短路或开路。4.检查电源模块是否过热,是否需要散热装置。5.检查电源模......
  • pipreqs 自动找到项目的所有组件和模块版本
    pipinstallpipreqs(适用于djangoFlask等)pipreqs./--encoding=utf-8找到当前项目目录下的所有组件和依赖H:\MyFlask>pipreqs./--encoding=utf-8十六.Flask基本项目目录搭建和pipreqs模块(组件和模块版本)virtualenv模块(创建虚拟环......