一、引言

最近,老大给了我一个学习研讨任务,也就是如何让 js 和 C++ 进行互调使用。比如我可以在网页中,使用 js 代码调用 c++ 函数,也可以在 c++ 函数中调用 js 对于界面进行控制。

这是为后期的软件接入 Html5 做技术调研。

那么如何实现呢?

这里需要感谢 Redrain 的博客给Webkit内核的浏览器控件增加互交功能,通过参考他的博客,加之我自己的探索,一步一坑终于完成了这个 demo。

如果想要直接看大神的博客可以点击上面那个链接,如果你是个跟我一样在之间一无所知的小白,那就可以看看我作为小白的一步一步的探索吧,应该会比上面大神的博客详细一些。

二、基于 SOUI 的浏览器控件

我这个浏览器 demo 是基于 SOUI 界面库,而 Redrain 的 demo 是基于 duilib 的。其中 SOUI 界面库是我工作中接触到的第一个开源的界面库,功能非常强大,感兴趣的同学可以点击这里 UI神奇-SOUI。

其实用的什么界面库在这里真的没有什么大的影响,因为都是同样封装了 wke 的浏览器内核来调用而已。那么 wke 是什么呢? wke 是 BlzFans (国内大神)对于 webkit 浏览器内核的一个小巧而又强大的封装库,可以实现浏览器内核的相关功能。

那么,怎么开始呢?我们就假设你已经有了一个可以访问网页的浏览器 demo 了,并且使用的是 wke 内核。接下来我们就一步一步的实现 js 和 c++ 之间的交互吧。

三、c++ 调用 js

首先,我们来实现稍微简单点的,c++ 调用 js。

如何实现呢?其实我们仔细翻看 wke.h 文件,就可以看到其实 blzFans 已经封装好了。我们打开 wke.h 文件,可以看到以下的两行代码:

virtual jsValue runJS(const utf8* script) = 0;
virtual jsValue runJS(const wchar_t* script) = 0;

通过函数名称,我们就可以推测这是调用 js 的方法,那么我们只需要在封装浏览器控件的地方,封装一个函数方法,调用 runJS() 方法即可。

这里我使用的是 SOUI 界面库,在 demo 里面已经封装好了一个基本成型的浏览器控件,这里直接在 SWkeWebkit类中添加 RunJS() 方法即可:

SStringW SWkeWebkit::RunJS(SStringW strValue)
{if (m_pWebView == NULL) return SStringW(L"wke 对象为空");jsValue jsRet = m_pWebView->runJS(strValue);return jsToStringW(m_pWebView->globalExec(), jsRet);
}

这里需要解释一下,SStringW是 SOUI 界面库封装的字符串类,我们将 wke 对象设置为 SWkeWebkit类的私有变量进行存储,这里由 m_pWebView就可以来调用 runJS() 方法调用 js 代码了。

值得一说的是最后的 return 句,这里是参考 Redrain 的代码写的,刚开始也不知道是什么含义,经过多次测试后发现,这一句可以用来返回可能需要返回的 js 代码结果,比如寻找一个元素后返回某些属性值什么的。

比如说,我在 demo 里面写了一个 index.html ,其中有这么一句代码:

<img id="img_track_event_id" name="img_track_event_name" class="" src="data:images/bd_logo.png" width="300" height="128" onmousedown="CallCPlusPlus()" />

这个 img 元素的 id 值为 img_track_event_id,name 值为 img_track_event_name,然后我们可以尝试用 c++ 调用 js 代码:

document.getElementById("img_track_event_id").name

来返回我们需要返回的 img 控件的 name 值。

这里可以看到,我在浏览器地址栏输入了 js 代码,并点击 run js 后,响应按钮信息,从地址栏获取到了 js 代码,运行后获取到了 js 返回的值,并以弹框形式显示出来。

这里我感觉我已经讲述的非常详细了,其中关于如何自己在本地建立一个静态的 html 文件进行测试还没有细说,下一节将会讲到,其他如果还有不懂的地方,可以参看我的 demo。

四、js 调用 c++

在之前,我们已经实现了 c++ 调用 js 的功能,是通过 wke 封装好的 runJS方法实现的。那么 js 调用 c++ 应该如何实现呢?

甚至有些人会问, js 调用 c++ 应该如何测试呢?

1. 创建测试网页

其实在上一节,我漏了很重要的一点没有讲述,那就是如何建立本地的网页测试。为什么要建立呢?因为我们要让 js 与 c++ 交互,就必定需要一个本地的可以测试的界面。

这里我在软件运行路径下,建立了一个文件夹 Html,在这个文件夹中建立了文件 index.html,这个 html 文件里面主要就是有一个 img 元素,用来响应指定的 js 方法。

<img id="img_track_event_id" name="img_track_event_name" class="" src="data:images/bd_logo.png" width="300" height="128" onmousedown="CallCPlusPlus()" />

至于这个 index.html文件如何书写,可以参看我的 demo 项目,这里就不再赘述了(其实作为一个小白,这一块我也是遇到坑了的,不过可以看代码解决的问题,就不在博客里说了,代码里一切都有)。

需要说一下的是,如何使用 wke 载入本地的 html 文件呢:

webView->loadFile(_T("Html/index.html"));
bool b = webView->isLoaded();

只需要让 wke 对象调用 loadFile方法即可,注意这里的路径设置,需要将 Html 文件夹放到程序的当前运行目录下(或许有些人会问,怎么知道程序的当前运行目录呢?一般都是 sln 的同级目录,不过也可以使用 GetCurrentDirectory函数来获取,我就是这么获取到的)。

到了现在,我们已经创建了测试的环境,并编写好了测试的网页元素,那么让我们开始吧!

2. 查看 wke 相关接口

首先,让我们看看 wke 提供的接口函数:

WKE_API void jsBindFunction(const char* name, jsNativeFunction fn, unsigned int argCount);
WKE_API void jsBindGetter(const char* name, jsNativeFunction fn); /*get property*/
WKE_API void jsBindSetter(const char* name, jsNativeFunction fn); /*set property*/

这里 jsBindFunction就是用来绑定 c++ 函数的方法。那么回调函数应该怎么写呢?

#define JS_CALL __fastcall
typedef jsValue (JS_CALL *jsNativeFunction) (jsExecState es);

Got it!

我们现在有了绑定的函数,有了回调函数,只要琢磨清除用法就可以使用了!

那么该如何使用呢?

首先,在 index.html 中写好我们触发的 js 函数:

<script type="text/javascript">function CallCPlusPlus() {msgBox("点击图片由 js 调用 C++ 弹窗", "提示");}
</script>

这里需要解释下的就是,msgBox我理解为就是一个标签,是一个什么标签呢?是用来在绑定的时候,让 wke 知道,哦,我在 js 中看到了 msgBox我就把它与某个 c++ 函数绑定起来,然后 msgBox函数里面自然可以传入参数。这样,通过这个标签,就完成了 js 和 c++ 对于同一个函数的认定响应。

然后,我们在 html 中编写能够触发我们这个 js 函数的元素:

<img id="img_track_event_id" name="img_track_event_name" class="" src="data:images/bd_logo.png" width="300" height="128" onmousedown="CallCPlusPlus()" />

注意这里选择了 onmousedown也就是鼠标单击行为触发此 js 函数,至此,我们已经完成了界面上需要做的事情。

再然后,我们到调用处,编写我们需要绑定的全局的 c++ 函数:

// 全局的 js 调用 c++ 的函数
jsValue JS_CALL jsMsgBox(jsExecState es)
{const wchar_t *text = jsToStringW(es, jsArg(es, 0));const wchar_t *title = jsToStringW(es, jsArg(es, 1));SOUI::SMessageBox(NULL, text, title, MB_OK);return jsUndefined();
}

这里需要解释下,jsMsgBox并不是我们之前在 js 函数中写的那个标签 msgBox 。我们在 js 函数里的只是一个绑定时 c++ 和 js 双方都认定的一个标签而已,c++ 函数的名称是可以随便取的,但是函数返回值和参数必须与 wke 声明一致。

另外,传入的参数只有一个es ,wke 通过 jsToStringW(es, jsArg(es, 0))来解析出函数所需要的参数。这里我们解析出来了两个参数,并使用 SMessageBox函数显示出来,这里的 SMessageBox是 SOUI 封装的弹框类。

最后,我们将 js 中的标签 msgBox 与 全局函数 jsMsgBox 绑定起来即可:

// 绑定 js 函数,让 js 主动调用 C++ 函数
jsBindFunction("msgBox", jsMsgBox, 2);

这里 jsBindFunction函数,第一个参数的含义就是 js 函数中使用到的标签,第二个参数是需要绑定的 c++ 函数名,第三个参数是参数个数。

至此,我们完成了 c++ 部分的编写。

现在,我们运行程序,点击 run c++ ,进入测试界面,点击图片,触发 js 方法,调用 c++ 方法,弹框:

成功撒花!!!

五、总结

这些实现的方法都不是我做的。

SOUI 界面库 是 SOUI 作者启程写的;
wke 浏览器内核是 BlzFans 写的;
js 和 c++ 互调方法是 Redrain 写的;

这里我只是摸索着他们的后路,将自己同样实现后的经验和感想分享。

最后,附上我的 demo 代码的 github 地址,希望能对有需要的同学有点启发,JsCplusplusInteractons。

基于 wke 的浏览器:如何实现 js 和 c++ 的互相调用相关推荐

  1. 基于asp.net + easyui框架,js实现上传图片之前判断图片格式,同时实现预览,兼容各种浏览器+下载...

    2019独角兽企业重金招聘Python工程师标准>>> 最近在做图片上传的一个前台页面,上传图片功能虽然很简单,但是需要我们学习的地方很多.在上传图片之前验证图片的格式,并同时实现预 ...

  2. 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理

    最近发现有不少介绍JS单线程运行机制的文章,但是发现很多都仅仅是介绍某一部分的知识,而且各个地方的说法还不统一,容易造成困惑. 因此准备梳理这块知识点,结合已有的认知,基于网上的大量参考资料,从浏览器 ...

  3. js中当等于最小值是让代码不执行_从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理...

    前言 见解有限,如有描述不当之处,请帮忙及时指出,如有错误,会及时修正. ----------超长文+多图预警,需要花费不少时间.---------- 如果看完本文后,还对进程线程傻傻分不清,不清楚浏 ...

  4. 原来浏览器原生支持JS Base64编码解码

    原来浏览器原生支持JS Base64编码解码 转载来源:https://www.zhangxinxu.com/wordpress/2018/08/js-base64-atob-btoa-encode- ...

  5. 基于Spring Boot 2 和 Vue.js 2 的 食品科学与工程学院网站的设计与实现

    摘要 互联网具有传播信息容量大.形态多样.迅速方便.自由和交互等特点,已经发展成为新的传播媒体,现在很多的大学和社会其他部门都已经建立了网站,通过计算机网络实现宣传.交流及资源的整合.建立学校网站有以 ...

  6. Firefox Profilemaker 基于Web的浏览器配置编辑器

    相信不少Firefox用户都有自己的浏览器配置习惯,但是在迁移或重装后的重配置过程却是一件费时费力的事情.不过本文介绍的Firefox Profilemaker,则是一款基于Web的浏览器配置编辑工具 ...

  7. 浏览器内核及js引擎

    找到一篇好文,mark一下: http://www.cnblogs.com/xiyangbaixue/archive/2014/10/22/4042548.html 摘要: 面试一个大公司的时候问到了 ...

  8. 浏览器内核与js引擎

    浏览器内核与js渲染引擎: 简介: 在维基百科上是这样介绍浏览器内核的,网页浏览器的排版引擎(Layout Engine或Rendering Engine)也被称为浏览器内核.页面渲染引擎或模板引擎, ...

  9. 浏览器内核和js引擎

    摘要: 面试一个大公司的时候问到了一个问题,让我谈谈主要的浏览器内核以及他们的特点,当时并没有详细的回答,回来之后自己在网上找了找资料,总结了下分享给大家. 简介: 在维基百科上是这样介绍浏览器内核的 ...

  10. JavaCV音视频开发宝典:无需流媒体服务也无需转码,使用JavaCV和springBoot实现http-flv转封装直播服务,浏览器网页flv.js直接播放rtp、rtsp、rtmp实时视频

    <JavaCV音视频开发宝典>专栏目录导航 <JavaCV音视频开发宝典>专栏介绍和目录 前言 本章代码除了在<JavaCV音视频开发宝典:使用JavaCV和spring ...

最新文章

  1. C++中explicit关键字的使用
  2. 批量探测工具fpingping常用命令集合大学霸IT达人
  3. vueRouter-命名视图
  4. 在一个数组中删除另一个数组存在的值
  5. Linux包系列的知识(附:Ubuntu16.04升级到18.04的案例)
  6. Linux设备模型:kset, kobj, ktype
  7. pytorch torchvision.transforms.Resize
  8. 保护你的眼睛,把电脑屏幕由白色改为淡绿
  9. 使用 paddle来进行文本生成
  10. Canon600D入手记
  11. openGL实现太阳系行星系统
  12. 【给量化行情插上翅膀】天翼云电脑上实践纯Python通过LMDB加速股票行情读写速度
  13. 计算机中的数学【费马大定理】 数学史上最著名的定理: x^n + y^n = z^n(n 2时,没有正整数解)...
  14. 【CV系列】颜色恒常性理论及应用
  15. Mixly 数码管时钟
  16. 蓝牙芯片NRF51822入门学习:时间管理
  17. maya拆完uv,画好贴图后导入,模型上贴图显示混乱
  18. 如何在2小时内用1块钱赚到100块钱?
  19. 西门子 s7-1200和V90伺服3轴PTO
  20. 华为文件Android可以删吗,原来华为手机里这些文件夹都可以删!删完立马多出几个G!真棒...

热门文章

  1. 评《Word排版艺术》-----佐岸
  2. C语言电影院售票系统
  3. cad残留卸载清理工具,强力清理CAD注册表残留
  4. 职称计算机考试excel内容,2020年职称计算机考试EXCEL试题练习
  5. 韩顺平JAVA学习笔记(入门自用)
  6. 17-基于51单片机的银行排队叫号系统设计
  7. Vue - 超详细最新 WangEditor V5 富文本编辑器安装引入及使用教程(内含在 Nuxt.js 项目中引入的解决方案)
  8. Hive Sql 安装
  9. Maya: Motion Graphics Workflow with MASH Maya教程:运动图形工作流程与MASH Lynda课程中文字幕
  10. 超详细的80个Python入门实例,代码清晰拿来即用,学习提升必备