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。
作者:无脑仔的小明 出处:http://www.cnblogs.com/wunaozai/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果文中有什么错误,欢迎指出。以免更多的人被误导。有需要沟通的,可以站内私信,文章留言,或者关注“无脑仔的小明”公众号私信我。一定尽力回答。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2015-12-14 Docker练习例子:基于 VNCServer + noVNC 构建 Docker 桌面系统