JS 与 C++ 双向通信实战:基于 WebHostViewListener 的消息处理机制

JS与底层C++通讯方式 JS与底层C++通讯方式 WebAssembly与Emscripten 1. Emscripten 为了在浏览器中运行C/C++程序,从1995年起,许多知名项目相继开发。除尝试直接运行本地C++代码外,也有技术人员另辟蹊径,将其他语言直接转译为JavaScript后运行,Emscripten就是其中一个,它利用LLVM编译器前端编译C++代码,生成LLVM特有的跨平台中间语言代码,最终再将LLVM跨平台中间语言代码转译为JavaScript的子集WebAssembly。这样C/C++程序经过编译后不仅 阅读详情

前言

在现代浏览器和桌面应用开发中,WebView 嵌入已经成为一种非常常见的 UI 技术方案。无论是基于 Chromium 的 CEF(Chromium Embedded Framework)、Qt WebEngine,还是自研浏览器内核,嵌入 WebView 都能带来极高的灵活性与跨平台 UI 开发能力。

不过,当 HTML/JavaScript 需要与 C++ 后端交互时,如何实现 高效、安全、可维护 的双向通信机制,就成了一个必须认真设计的问题。本文将结合 WebHostViewListener 机制,从源码角度深入剖析 HTML/JS 与 C++ 的消息传递、事件处理、数据序列化等关键流程,并对比常见的 JSBridge、JavaScriptCore 等方案,总结优缺点与优化建议。


一、为什么需要 WebView 与 C++ 双向通信

嵌入 WebView 的目的不仅仅是“显示网页”,而是利用 HTML/CSS/JS 的灵活 UI 构建能力,与 C++ 的高性能、底层资源访问能力结合。

典型的交互场景包括:

  1. HTML/JS 调用 C++ 功能

    • 获取本地文件列表

    • 调用系统 API(如打开文件、读取剪贴板)

    • 访问数据库或加解密模块

    • 发送网络请求并处理复杂协议

  2. C++ 回调 HTML/JS

    • 通知前端状态变化(如下载进度、后台任务完成)

    • 推送实时数据(如 WebSocket 消息)

    • 动态修改前端 UI(更新 DOM 或触发 JS 方法)

如果没有合理的通信机制,前后端之间会出现:

  • 数据结构不统一

  • 消息无法安全传输

  • 调用关系混乱、难以调试

而 WebHostViewListener 正是为了解决这些痛点而设计的一个消息分发与事件监听器。


二、WebHostViewListener 的定位与职责

在一个基于浏览器内核的应用中,WebHostViewListener 通常作为 桥接层(Bridge Layer) 的核心部分,负责监听 WebView(浏览器渲染进程)与 C++ 宿主(浏览器主进程或宿主应用)之间的消息,并进行分发与处理。

其核心职责包括:

  1. 监听 HTML/JS 发出的消息

    • 通过 WebView 内置的消息通道(如 window.external、chrome.send、window.postMessage)接收 JSON 数据

    • 解析消息并根据指令类型路由到对应的 C++ 处理逻辑

  2. 将处理结果返回给前端

    • 将 C++ 的执行结果序列化为 JSON

    • 通过 WebView 的 JavaScript 执行接口(如 ExecuteJavaScript、RunJSFunction)回调给 HTML 页面

  3. 保持通信协议一致性

    • 定义统一的消息格式:消息类型、参数、回调 ID

    • 确保版本升级时协议向后兼容


三、消息格式设计

要实现稳定的双向通信,首先需要一个 统一的消息格式。在 WebHostViewListener 中,常见的设计是基于 JSON 的结构化消息,例如:

{ "cmd": "getUserInfo", "params": { "userId": 12345 }, "callbackId": "cb_001" } 

字段解释:

  • cmd:指令名,告诉 C++ 需要执行什么操作

  • params:参数对象,包含该操作需要的输入数据

  • callbackId:回调 ID,前端用它来区分不同请求的返回

返回给前端的消息同样保持结构化,例如:

{ "callbackId": "cb_001", "status": 0, "data": { "name": "Alice", "age": 25 } } 

这样设计的好处是:

  • 协议简单明了

  • 支持异步回调

  • 易于调试与扩展


四、WebHostViewListener 的工作流程

假设我们有这样一个交互场景:

  1. 前端 HTML 通过 JavaScript 发送一个 getUserInfo 请求

  2. C++ 收到消息后查询数据库

  3. 查询结果再通过 WebView 回调给前端

对应的流程图如下:

HTML/JS ----(消息)----> WebHostViewListener(C++) <---(回调)----- 

1. 前端发送消息

前端调用封装的发送方法,例如:

function sendMessage(cmd, params, callback) { const callbackId = "cb_" + Date.now(); window.WebHostView.postMessage(JSON.stringify({ cmd: cmd, params: params, callbackId: callbackId })); callbacks[callbackId] = callback; } sendMessage("getUserInfo", { userId: 12345 }, function(response) { console.log("User Info:", response.data); }); 

2. WebHostViewListener 接收消息

在 C++ 中,WebHostViewListener 会注册一个 消息回调函数:

void WebHostViewListener::OnMessageReceived(const std::string& json_message) { auto msg = ParseJson(json_message); std::string cmd = msg["cmd"]; if (cmd == "getUserInfo") { HandleGetUserInfo(msg["params"], msg["callbackId"]); } } 

3. C++ 处理逻辑

void WebHostViewListener::HandleGetUserInfo(const Json::Value& params, const std::string& callbackId) { UserInfo info = database_.GetUser(params["userId"].asInt()); Json::Value result; result["name"] = info.name; result["age"] = info.age; SendCallback(callbackId, 0, result); } 

4. 回调前端

void WebHostViewListener::SendCallback(const std::string& callbackId, int status, const Json::Value& data) { Json::Value msg; msg["callbackId"] = callbackId; msg["status"] = status; msg["data"] = data; std::string json_str = msg.toStyledString(); webview_->ExecuteJavaScript("window.onNativeMessage(" + json_str + ");"); } 

五、与常见 JSBridge 的区别

你提到的 优快云 文章中介绍的方式,更多是基于 JavaScript 调用绑定函数 的模式,例如:

  • 在 WebView 中注入一个 window.external.callCppMethod() 的接口

  • 或使用 CEF 提供的 ExecuteFunction 注册回调

这种方式的特点:

  • 实现简单,适合调用频率低的功能

  • 消息结构不一定规范,容易出现维护问题

  • 缺少统一的异步回调机制

而 WebHostViewListener 的优势在于:

  • 协议化:统一 JSON 消息格式

  • 可扩展:只需新增 cmd 处理函数即可

  • 异步友好:支持多并发调用,回调不会乱序


六、性能与安全性考虑

在大规模应用中,通信机制需要关注以下几个点:

  1. 消息序列化与反序列化开销

    • 频繁 JSON 解析会有性能损耗

    • 可考虑二进制格式(如 Protobuf)优化

  2. 安全性

    • 严格校验 cmd 是否在允许列表

    • 检查 params 数据类型,防止注入攻击

  3. 线程模型

    • UI 线程接收消息,耗时操作放到后台线程

    • 回调 UI 必须切回主线程


七、实际案例:浏览器插件配置面板

以我在浏览器项目中的一个场景为例:

  • 前端是 HTML/JS 的插件配置界面

  • 需要读取/写入本地配置文件

  • 修改配置后立即生效

采用 WebHostViewListener:

  • 前端发送 "saveConfig" 消息

  • C++ 写入 JSON 配置文件

  • 成功后回调 "status": 0

  • 前端立即刷新界面

这种模式非常清晰,扩展新功能时,只需要新增一个 cmd 分支,不会影响已有功能。


八、总结

WebHostViewListener 提供了一种结构化、可维护、扩展性强的 WebView 与 C++ 双向通信机制,它相较于简单的 JS 调用绑定函数模式,在复杂项目中更具优势。

它的核心思想:

  • 协议化(统一 JSON 格式)

  • 模块化(cmd 分发)

  • 异步化(callbackId 回调)

在浏览器、桌面客户端、混合应用等场景下,都可以直接借鉴这种设计思路。

webview:适用于C ++的跨平台Webview库 网页浏览 一个小型的跨平台Webview库,使用Windows上的Edge(EdgeHTML和Chromium),MacOS上的Webkit和Linux上的WebkitGTK用C ++编写。 受到zerge的启发,该库被重写为以下几项优先事项: 更像“ C ++”的API 在Windows上支持Microsoft Edge 用实际的Objective-C代码替换了Objective-C运行时C代码 支持 视窗 苹果系统 Linux 版本 Windows 10,v1809 + 已在Catalina的MacOS Mojave上测试 在Ubuntu 18.04.02 LTS上测试 网页引擎 EdgeHTML / Chromium 网页套件 网页套件 图形用户界面 Windows API 可可 GTK 用法 // main.cpp # include " webview.h " 立即下载

相关推荐

Websocket的C++服务端和JS客户端通信DemoV2

1 开发环境 - Visual Studio 2015 - Javascript - Windows 10 Pro x64 2 功能介绍 演示Websocket的C++服务端和JS客户端通信。 3. 接口文档

C++ 在Win32中简单使用WebView2

c++ Win32简单使用WebView2

qq_40218744的博客 1万+

Palabos User Guide中文解读 | 第五章 | Palabos编程 (跳过了第四章Palabos-Java接口)

作者的话:本人在学习palabos时,发现国内中文资料甚少,恰好网上可以直接搜到palabos user guide这种英文资料,加之时间充裕,便打算开始翻译,翻了一节后发现这可能算侵权,就比较伤脑筋,突然想到自己写中文解读即可,便有了下面的博客。 Palabos User Guide Release 1.0 r1 Copyright © 2019 University of Geneva Jul...

Yulan Fang's notes. 2297

WebView2教程(基于C++)【一】环境初始化

中,以后我们会从这个d中获取配置信息。执行之后,就创建了一个App对象,这个对象被保存在静态变量app中,在App的构造函数中,先初始化了应用程序的配置信息。在这个方法中,webview2的环境对象被保存到静态变量webViewEnv中了,接着创建了窗口对象,并保存到一个容器wins中(静态变量)。这个方法会判断当前的用户环境,是否安装了WebView2的运行时,如果没有,则打开一个网页,让用户去下载WebView2的运行时。如你所见,依据我们的配置文件,我们是可以在应用程序启动时,直接创建多个窗口的。

liulun的博客 3757

Concentration Inequality(集中不等式)更新版

欢迎来我博客 https://wyue.name/2020/04/17/1/阅读这一篇博文 转载前请联系我,联系方式请见我博客 https://wyue.name/ Concentration inequality 刻画了一组随机变量的和(或者样本平均数)与其期望值的偏离程度,在算法收敛性分析过程中是非常有用的一类不等式。 这次主要总结一下最近一段时间遇到的集中不等式,不仅是不等式形式,...

Yue的博客 4554

永久关闭Windows更新的5种方法

很多家用电脑,如果系统自动更新的话,会变得越来越卡顿,且硬件型号兼容也并不完美。那么我们该如何彻底关闭Win11的自动更新呢?以下准备了5种方法,您可以根据自身实际情况选择合适的方法!

qq_43652793的博客 1万+

webview - 一个轻量级的跨平台网页视图库

webview - 一个轻量级的跨平台网页视图库 项目介绍 webview 是一个用于 C/C++ 的轻量级跨平台网页视图库,旨在为最常见的平台创建一个统一的 HTML5 UI 抽象层。该库支持两种语言的双向绑定,允许从 C/C++ 调用 JavaScript,以及从 JavaScript 调用 C/C++。 项目快速启动 以下是基于 CMake 的快速启动指南,适用于创建一个简单的 webvie...

gitblog_00409的博客 885

Test-Time Adaptation Induces Stronger Accuracy and Agreement-on-the-Line

TTA不管是否提高了OOD的泛化性都增强了线性的趋势,TTA的初始目的是为了增强OOD的表现,一个人可能会觉得TTA使得ACL更强的原因是他消除了ID和OOD之间的差距,因此所有模型间ID vs OOD的准确率接近于y=x这条线,但是实际上这个解释不能够反映我们的经验发现,因为虽然TTA将分布之间的偏移简化为一种放缩的分布,但是这个放缩的因子幅值可能很大,也就是α<<1但是r>>1,这就会导致很偏离y=x这条线,而且理论分析也是,虽然ID和OOD的差距很大,但是线性关系还在。

m0_62673638的博客 147

【小沐学C++】C++ MFC中嵌入web网页控件(WebBrowser、WebView2、CEF3)

WebBrowser控件最常见的用途之一是向应用程序添加 Internet 浏览功能。使用 IWebBrowser2 接口,可以浏览到本地文件系统、网络或万维网上的任何位置。可以使用IWebBrowser2::Navigate 方法告知控件要浏览到哪个位置。第一个参数是包含位置名称的字符串。要浏览到本地文件系统或网络上的某个位置,请指定文件系统位置的完整路径或网络上该位置的 UNC 名称。若要浏览到万维网上的某个站点,请指定该站点的 URL。╮( ̄▽ ̄)╭。

爱看书的小沐 9375

网络层隧道技术之ICMP隧道(pingTunnel/IcmpTunnel)

目录 ICMP隧道 使用ICMP搭建隧道(PingTunnel) 使用ICMP搭建隧道(Icmptunnel) ICMP隧道 ICMP隧道简单实用,是一个比较特殊的协议。在一般的通信协议里,如果两台设备要进行通信,肯定需要开放端口,而在ICMP协议下就不需要。最常见的ping命令就是利用的ICMP协议,攻击者可以利用命令行得到比回复更多的ICMP请求。在通常情况下,每个ping命令都有相...

谢公子的博客 6694

基于Spring Boot + Vue 3构建高并发华为数码商城交易平台:全栈架构设计与实现

内容将涵盖系统架构、数据库设计、核心模块开发(用户、商品、订单、购物车)、安全认证、性能优化以及前后端分离部署等关键环节,并提供详尽的代码示例,旨在为开发者提供一个可落地的企业级项目实战指南。<el-button text class="button" @click.stop="addToCart(product)">加入购物车</el-button>.antMatchers("/api/user/login", "/api/user/register").permitAll() // 公开接口。

2201_76125393的博客 306

使用c++写一个调用webview的简易浏览器

使用C语言编写一个简易浏览器,需要使用webview技术,首先需要引入webview头文件,然后定义窗口参数,最后创建一个webview对象,调用webview的loadurl函数来加载需要显示的网页。 ...

weixin_35755823的博客 735

VLA数据采集以及训练

直到15s计时结束,弹出下面的内容,这个时候不会录制视频了,这里就是需要复位物体到初始位置,尽量保证物体的初始位置放在一样的位置,计时3s,同样根据自己的复位时间来修改(--dataset.reset_time_s=3),这里和前面录制数据的区别就是fps后面多了一个nment,可以作为一个标记,知道什么时候开始去复位而不会拍到自己的手臂。复制网址,在浏览器打开,会出现下面的窗口,依次检查每一轮是否存在问题,例如是否出现录制不完整,是否存在除了机械臂以外的其他移动物体,这些都可能会影响最终训练的效果。

weixin_45303602的博客 496

C++使用WebView2控件,通过IPC通信与Javascript交互

在现代桌面应用程序开发中,Web技术与原生应用的融合变得越来越普遍。Microsoft的WebView2控件为C++开发者提供了一个强大的工具,使他们能够在桌面应用中嵌入基于Chromium的Web浏览器引擎。本文将详细介绍如何在C++应用程序中使用WebView2控件,并通过IPC(进程间通信)机制实现C++与JavaScript之间的双向交互。

exlink2012的专栏 2463

UCIE Specification详解(五)

Logical Physical Layer(逻辑物理层)

Crazzy_M的博客 1219

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

WebView2教程(基于C++)【五】JS与C++互访(下)

这些接口定义允许不同编程语言编写的组件相互通信,是实现组件对象模型(COM)、远程过程调用(RPC)和对象管理组(OMG)的CORBA等技术的关键元素。JavaScript代码拿到C++对象之后,就可以调用C++对象提供的方法了。现在我们写JavaScript代码,来调用HostImpl对象的这个CloseWindow。编译运行程序,你会发现输出目录下就有这个tlb文件,这个文件的名字别搞错了。生成的代码文件我们不用管,我们要做的是实现这个接口的类:HostImpl。下面是HostImpl.h的代码。

liulun的博客 1819

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Android开发学习笔记:浅谈WebView

WebView(网络视图)能加载显示网页,可以将其视为一个浏览器。它使用了WebKit渲染引擎加载显示网页,实现WebView有以下两种不同的方法: 第一种方法的步骤: 1.在要Activity中实例化WebView组件:WebView webView = new WebView(this); 2.调用WebView的loadUrl()方法,设置WevView要...

weixin_33966095的博客 306

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

WebView基本使用

WebView基本使用 //初始化 webview= (WebView) findViewById(R.id.webView); //或者代码生成 WebView webview =new WebView(this); //垂直不显示滚动条 webview.setVerticalScrollBarEnabled(false); //声明W

残梦 508

WebView实战开发:构建跨平台桌面应用

WebView实战开发:构建跨平台桌面应用 【免费下载链接】webview Tiny cross-platform webview library for C/C++. Uses WebKit (GTK/Cocoa) and Edge WebView2 (Windows). ...

gitblog_00300的博客 648

WebView API详解:C/C++接口完全指南

WebView API详解:C/C++接口完全指南 【免费下载链接】webview Tiny cross-platform webview library for C/C++. Uses WebKit (GTK/Cocoa) and Edge WebView2 (Windows). ...

gitblog_00598的博客 809

C++与JS实现WebSocket通信(C++服务端JS客户端)

java实现websocket(java客户端java服务端)js实现websocket(html客户端js服务端)c++实现websocket(c++服务端c++客户端)

感谢阅读 1806

Webview 项目使用教程

Webview 项目使用教程 1. 项目的目录结构及介绍 Webview 项目是一个轻量级的跨平台网页视图库,用于在 C/C++ 应用程序中嵌入网页界面。项目的目录结构如下: webview/ ├── .github/ # GitHub 相关配置文件 ├── cmake/ # CMake 相关文件 ├── compatibility/ ...

gitblog_00722的博客 461

WebView2教程(基于C++)【四】JS与C++互访(上)

C++中要想接收消息,必须注册一个WebMessageReceived事件,我们可以在JS中,通过postMessage方法向C++发送消息,代码如下。

liulun的博客 1926

JS调用C++ .

1.注册C++函数。 [cpp] view plaincopyprint? //注册回调函数宏   //根据不同需要支持注册两个函数原型,注意CONNECT_JS_CALL_SIMPLE_HANDLER中注册的函数   //需要提前和HTML调用协调好,参数必须都为字符,负责会引起未知问题   #define CONNECT_JS_CALL_HANDLER(name

bible521125的专栏 1025

WebView2教程(基于C++)【二】第一个窗口

其中值得注意的就是WM_SIZE消息,在窗口大小改变的时候,我们也改变了WebView2控件的大小。(一个窗口中可能有多个WebView2控件)构造函数的输入参数是配置文件config.json中windows数组的一项,你可以在上一篇中会看到config.json的代码。这里用到了一个areaToRect方法,用于把配置文件中的配置信息转化成RECT。这里需要注意的是,如果配置文件中frame设置成false,则窗口就是无边框窗口。initSizeAndPos方法根据配置文件的信息确定窗口的位置和大小。

liulun的博客 1700

微信小程序web-view与H5之间交互(含支付)

微信小程序使用web-view加载H5的方式,往往纯加载并不能满足业务需求,这个时候就得了解小程序与H5的交互。提示:以下是本篇文章正文内容,下面案例可供参考本文简单介绍了小程序web-view与H5的交互,若有其他更好的交互方式,欢迎评论区补充。未完待续...

Rocky_Time的博客 1万+
上一篇: 如何让自己更稳重、更有气场?——从内到外的系统修炼指南
下一篇: 深入解析 Chrome UI 布局配置的设计思想与实现机制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ปรัชญา แค้วคำมูล

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值