首先需要明确:JS代码本身不具备直接调用系统API的能力,JS代码能调用什么功能,都依赖于其它扩展模块提供了什么样的接口。

soui4js模块将soui的界面能力作为一个js模块导出到了js中,使得js可以和C++一样操作GUI。

但是操作GUI只是一个客户端APP的一个需求。一个产品可能会有各种需求是现有模块不能实现的,或者是能性能要求很高不宜使用JS实现的。

这就需要用户自己使用如C/C++这样的语言来扩展js模块。

soui4js的代码中有一个模块utils,它就是一个典型的扩展模块。

在该模块中,我们导出了几个文件操作,编码转换方法。用户要扩展自己的模块,只需要参考utils模块来增加自己的API即可。

utils模块是一个dll项目,编译后生成一个utils.dll

该dll导出两个方法:

 1 extern "C"
2 __declspec(dllexport) JSModuleDef* js_init_module(JSContext* ctx, const char* module_name)
3 {
4 qjsbind::Context* context = qjsbind::Context::get(ctx);
5 if(!context)
6 context = new qjsbind::Context(ctx);
7 qjsbind::Module *module = context->NewModule(module_name);
8 Exp_Utils(module);
9 return module->module();
10 }
11
12 extern "C"
13 __declspec(dllexport) void js_uninit_module(JSContext * ctx)
14 {
15 qjsbind::Context* context = qjsbind::Context::get(ctx);
16 if(context && context->isAttached())
17 delete context;
18 }
js_init_module是在quickjs加载扩展模块时调用。这个函数的功能就是给JSContext匹配一个qjsbind::Context对象。
对于UI线程来的模块,JSContext中已经有了Context对象,但是worker线程import创建的module,JSContext中是没有qjsbind::Context对象的。此时我们需要new一个新的qjsbind::Context对象出来。
然后调用自己实现的Exp_Utils(module)方法来导出C++方法到JS中。
js_uninit_module是quickjs在释放一个module时调用(注:这是soui4js使用的quickjs扩展的功能,原版qjs没有该逻辑)
这里主要是释放在js_init_module中new的qjsbind::Context对象,防止内存泄漏。
下面我们看一下Exp_Utils的代码
void Exp_Utils(qjsbind::Module* module)
{
module->ExportFunc("Md5", &Md5);
module->ExportFunc("FileMd5", &FileMd5);
module->ExportFunc("FileMd5Ex", &FileMd5Ex);
module->ExportFunc("DelFile", &fileop::DelFile);
module->ExportFunc("DelDir", &fileop::DelDir);
module->ExportFunc("SelectFile", &fileop::SelectFile);
module->ExportFunc("CopyFile", &fileop::JsCopyFile);
module->ExportFunc("CopyDir", &fileop::JsCopyDir); module->ExportFunc("Base64Decode", &Base64Decode);
module->ExportFunc("Base64Encode", &Base64Encode); module->ExportFunc("UrlDecode", &urldecode);
module->ExportFunc("UrlEncode", &urlencode); module->ExportFunc("PlaySound", &sysapi::JsPlaySound);
}
 module->ExportFunc("Md5", &Md5); 这一行的意思是将C++函数Md5导出到JS中,名字就是"Md5"。
下面我们看一下Md5函数的原型:
std::string Md5(const char* buf, int length) {
unsigned char digest[16];
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, (const unsigned char*)buf, length);
MD5Final(digest, &context);
return MDPrint(digest);
}
可以看出,这个函数和普通的C函数并没有什么不同。所有输入输出参数和JS的交换都在qjsbind中自动进行了处理。

Exp_Utils方法中,使用qjsbind::Module->ExportFunc方法,非常方便的实现了将C++方法导出到JS中。

qjsbind中对于常见的数据类型都做了处理。但是如果要支持用户自己的特定数据类型,则还是需要用户自己对特定参数类型做模板特化。

如果一个特殊类型的输入输出参数只在一个导出函数里使用,也可以使用手动参数类型转换,这样就不需要做参数的模板特化了。

方法很简单,定义一个形式如下的函数:

1 Value Test(qjsbind::Context *ctx, ArgList& args) {
2 SLOGI2("test") << args.size();
3 return undefined_value;
4 }

这里函数的参数及返回值都是固定的。ArgList & args里有从js传递过来的参数列表,你可以手动识别并转换成你需要的数据类型。函数执行完成后,再自己返回自己期望的类型即可。

注意:
原本quickjs也提供了开发扩展模块的框架,在原框架中,用户导出一个函数到JS要逐个处理qjs的输入输出参数,使用起来比较麻烦,使用本文的方法,借助qjsbind模块提供的模板方法,可以更简单方便的实现这个过程。

认识soui4js(第3篇):使用C/C++开发扩展模块的更多相关文章

  1. 【基于WinForm+Access局域网共享数据库的项目总结】之篇一:WinForm开发总体概述与技术实现

    篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...

  2. 【基于WinForm+Access局域网共享数据库的项目总结】之篇二:WinForm开发扇形图统计和Excel数据导出

    篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...

  3. 【转】iOS开发UI篇—iPad和iPhone开发的比较

    原文网址:http://www.cnblogs.com/wendingding/p/3918007.html iOS开发UI篇—iPad和iPhone开发的比较 一.iPad简介 1.什么是iPad ...

  4. 和S5933比较起来,开发PLX9054比较不幸,可能是第一次开发PCI的缘故吧。因为,很多PCI的例子都是对S5933,就连微软出版的《Programming the Microsoft Windows Driver Model》都提供了一个完整的S5933的例子。 在这篇有关DDK的开发论文里。

    和S5933比较起来,开发PLX9054比较不幸,可能是第一次开发PCI的缘故吧.因为,很多PCI的例子都是对S5933,就连微软出版的<Programming the Microsoft Wi ...

  5. Repractise基础篇:Web应用开发七日谈

    Repractise基础篇:Web应用开发七日谈 本来想的仅仅是画一个例如以下的七日图来说说Web开发的.随后又想了想这似乎是一个非常棒的Web开发相关的知识介绍.应用开发是一个非常有意思的循环,多数 ...

  6. silverlight,WPF动画终极攻略之番外 3D切换导航篇(Blend 4开发)

    原文:silverlight,WPF动画终极攻略之番外 3D切换导航篇(Blend 4开发) 这篇介绍的是3D导航,点击图标,页面360°翻转的效果!有什么不足的欢迎大家指出来. 1.新建一个user ...

  7. silverlight,WPF动画终极攻略之白云飘,坐车去旅游篇(Blend 4开发)

    原文:silverlight,WPF动画终极攻略之白云飘,坐车去旅游篇(Blend 4开发) 这章有点长,所以我分成了两章.这一章主要是准备工作,差不多算美工篇吧,这章基本不会介绍多少动画效果,主要讲 ...

  8. silverlight,WPF动画终极攻略之迟来的第三章 动画整合篇(Blend 4开发)

    原文:silverlight,WPF动画终极攻略之迟来的第三章 动画整合篇(Blend 4开发) 有个问题想请教下大家,我仿了腾讯的SL版QQ,相似度95%以上.我想写成教程教大家怎么开发出来,会不会 ...

  9. silverlight,WPF动画终极攻略之会飞的小鸟篇(Blend 4开发)

    原文:silverlight,WPF动画终极攻略之会飞的小鸟篇(Blend 4开发) 本教程基本涵盖了WPF和silverlight中的各种动画.先上张效果图. 声明下,这个做的不是让大家照搬的,只是 ...

  10. silverlight,WPF动画终极攻略之阳光灿烂篇(Blend 4开发)

    原文:silverlight,WPF动画终极攻略之阳光灿烂篇(Blend 4开发) 前面我们画了一只会飞动的小鸟,今天我们在目标是一个会发光的太阳.本章节的动画虽然简单,但是实现的效果可是一点也不打折 ...

随机推荐

  1. 从零开始的Python世界生活——内置模块(Math)

    从零开始的Python世界生活--内置模块(Math) Python的math模块提供了丰富的数学函数和常数,支持基本的数学运算.三角函数.对数.指数等,适用于科学计算和工程应用. 数学常量: 注意m ...

  2. python获取zabbix监控项图形

    python获取zabbix图形 通过zabbix的api接口获取指定时间段的监控项图形 图片示例: 代码示例: # -*- coding: UTF-8 -*- #可根据监控项获取zabbix下所有主 ...

  3. Limit线段树题单题解(更新中)

    P3373 线段树模板 2 \(1 \leq n \leq 10^5\) 题解:考查标记与标记的合并 我们考虑打两个懒惰标记实现区间乘和区间加 线段树维护区间和 对于信息与信息的合并:左儿子加上右儿子 ...

  4. Mybatis【11】-- Mybatis Mapper动态代理怎么写?

    目录 1.回顾Mybatis执行sql的流程 2.mapper动态代理怎么写? 3.mapper动态代理怎么做的? 1.回顾Mybatis执行sql的流程 在之前的代码中我们的运行过程再梳理一下,首先 ...

  5. Linux C/C++编程中的多线程编程基本概念

    8.2.1  操作系统和多线程 要在应用程序中实现多线程,必须有操作系统的支持.Linux 32位或64位操作系统对应用程序提供了多线程的支持,所以Windows NT/2000/XP/7/8/10是 ...

  6. ORCA避障源码笔记

    参考资料 https://gamma.cs.unc.edu/ORCA/publications/ORCA.pdf https://gamma.cs.unc.edu/RVO2/ 数学知识 1.向量的点乘 ...

  7. Win10虚拟机安装Docker解决Docker Engine Stopped问题记录

    跟着网上的帖子开启WSL2安装DockerDesktop, 但是无法启动Docker,一直[Docker Engine stopped] 继续跟着网上的帖子解决问题,检查电脑各种配置都搞一通后还是无法 ...

  8. 清理docker logs

    1,docker ps找到id [root@mysql3 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1d8 ...

  9. R数据分析:生存数据的预测模型建立方法与评价

    之前写了生存分析列线图的做法,列线图作为一个预测模型可视化工具,我们使用它的过程其实就是一个给新数据做预测的过程,其内在本身的模型就是我们基于现有数据训练的一个预测模型,今天也算是接着上一篇文章继续写 ...

  10. R数据分析:国产新冠口服药比辉瑞好的文章的统计做法分享

    元旦前在人民日报中央厨房上看到一篇文章,叫做"比肩辉瑞的国产新冠药物VV116,是这样研制和临床试验的",想来就把文献原文找来读了读,写下本文分享给大家,本文主要关注文章的正文中主 ...