0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅析cef在win和mac上的适配

京东云 来源:jf_75140285 作者:jf_75140285 2025-10-14 16:06 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

背景

cef是一种跨平台的框架,属于chrome内核,可以用来显示web相关页面。目前在咚咚工作台上使用,显示聊天框,历史消息,插件页面等等。之前只是在win平台上使用,在今年开发mac版本商家咚咚过程中,完成了mac版本的适配,积累了一些在两个平台上的使用方法,避免以后再踩坑。



一. 库和资源文件

基本的库文件包含了多个文件夹和资源文件,这些是运行cef时必须要依赖的,因此需要打包在安装包中。

win mac 说明
include文件夹 include文件夹 cef内部接口对外暴露的头文件
libcef_dll文件夹 libcef_dll文件夹 cef对外的wrapper库相关的cc文件
Resources文件夹 Resources文件夹 cef依赖的pak文件
libcef.dll Chromium Embedded Framework cef核心库文件
其它dll库,libEGL.dll等 其它dylib库,libEGL.dylib等 cef依赖动态库文件
其它bin文件,natives_blob.bin等 cef依赖bin文件

表1.1 cef依赖文件

以上是cef运行时所依赖的所有文件,其中include和libcef_dll, 可以组合生成一个lib静态库,一般名称为libcef_dll_wrapper.lib,在其它模块中需要依赖该cef头文件时,导入lib库即可。

在升级cef版本的过程中,只需要替换替换对应的文件夹中的文件,就可以升级到对应的版本,目前最新的100以上的版本,基本都是这些固定的文件格式。

如果添加了新的文件或者依赖库,则需要添加对应的库和资源。



二. 文件路径查找

资源文件,需要设定路径才能找到对应的文件,在CefSettings指定对应的路径。

路径 win mac
resource目录(pak文件) resources_dir_path framework_dir_path/main_bundle_path
locales目录 locales_dir_path framework_dir_path/main_bundle_path
子进程路径 browser_subprocess_path browser_subprocess_path

表2.1 cef资源路径设置

2.1 对于资源路径,win版本可以放到同一目录下面,例如在安装目录下,新建一个CEF目录,专门用来放置资源文件:

wKgZO2juBIqAKd7-AADmXxEim_A370.png

2.2 dll库则在主安装目录下面:

wKgZPGjuBIuASeKYAAGGxOjU71w170.png

2.3 mac版本的目录文件基本是固定的:

Chromium Embedded Framework.framework

一般可以放置到app包的顶层或者Frameworks目录下面

wKgZO2juBIuACpVoAADxKOjYMtI913.png



以上的路径,都需要明确指定绝对路径,即完整的访问路径资源,不能使用相对路径,比如../../../之类的,因此在程序内部,需要专门封装查找资源路径的方法,这样在应用安装到用户电脑上,才能准确找到对应的资源。

若资源文件无法找到,则在后续的初始化,第一步就会报错,只有找到文件,才能进行后续的步骤。



三. 主进程初始化

主进程初始化分为多个步骤:

wKgZPGjuBIyAbzsqAAL9n25qZf4389.png



3.1 加载cef动态库

如果将libcef库放置在标准目录下面,即win是exe同级目录,则无需查找动态库,系统可以自行查找到,如果放到其它目录,则需要采用动态加载库的方式。

mac可以使用cef提供的标准方法:

CefScopedLibraryLoader library_loader;

library_loader.LoadInMain()

来直接加载主进程库。

若采用显示路径来加载的方式,可以指定

Chromium Embedded Framework.framework下面的Chromium Embedded Framework,整个的完整路径

然后使用cef提供的方法:cef_load_library,加载指定路径下的主进程文件。

加载主库必须成功,失败则直接返回,后续一切步骤都依赖主进程的加载完成。

3.2 获取启动参数

启动的时候,都需要使用CefMainArgs,来获取命令行的参数

win mac
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); CefMainArgs main_args(hInstance); CefRefPtr command_line = CefCommandLine::CreateCommandLine(); command_line->InitFromString(::GetCommandLineW()); CefMainArgs main_args(argc, argv); CefRefPtr command_line = CefCommandLine::CreateCommandLine(); command_line->InitFromArgv(argc, argv);
使用系统方法,直接获取命令行参数 从main方法传递argc, argv,从中获取命令参数

表3.1 cef获取启动命令

接着生成 CefRefPtr app,这个类继承自cef的基本app类:CefApp

继承ClientApp,来生成主进程方法:

app = new ClientAppBrowser();

3.3 设置其它参数

设置日志级别:settings.log_severity

日志目录:settings.log_file

浏览器版本和说明:settings.user_agent

调试时的端口:settings.remote_debugging_port

3.4 主进程初始化

直接调用CefInitialize(main_args, settings, app.get(), sandbox_info)

传入命令,设置选项,app实例,sandbox的内容,通常来说sandbox为空,不启用即可

返回成功可以进行后续步骤,失败表示主进程启动异常,后续也无法显示页面。



四.渲染进程生成

渲染进程,可以采用和主进程合并模式,也可以采用单独的进程。一般比较大型或者复杂的项目,都需要单独的进程,并为了不同的页面,还需要启动多个子进程。

启动流程和主进程类似,先加载子进程路径,再获取命令行参数,继承CefApp启动实例,最后再初始化。

进程名称,win可以自己定义,mac有严格限制,必须以xxx Helper结尾,否则找不到对应的渲染子进程。

win mac
独立的exe应用 独立的app应用
子进程名称.exe 子进程核心应用:xxx Helper.app 子进程GPU应用:xxx Helper (GPU) 子进程Plugin应用:xxx Helper (Plugin) 子进程Render应用:xxx Helper (Renderer)

表1.1 cef子进程名称

4.1 子进程的路径,理论上可以设置到专门的目录下面,但也可以让系统去默认路径查找,即和主应用同级别即可。

加载cef资源的时候,win版本在主应用同级别的exe,不用专门的方法去加载。

mac版本需要使用cef的专用方法:

CefScopedLibraryLoader library_loader;

library_loader.LoadInHelper()

若是需要专门的路径,则仍然使用cef_load_library去加载库的绝对路径,加载成功后,才能正常初始化子进程。



4.2 在最后初始化时,可以直接调用cef的方法:

CefExecuteProcess(main_args, app, nullptr)

返回值大于0,表示启动子进程已经成功,可以开启渲染页面等操作。

返回值小于0,表示启动子进程失败,页面将无法进行渲染,但是不影响主进程的正常运行。

子进程实现的最好方式,是将所有的依赖文件,都集成在同一个模块工程中,不依赖其它的模块,这样在编译运行的时候,就不会由于依赖过多导致各种错误。



五. 消息循环

不同的系统版本中,采用不同的消息循环模式,需要和主应用的消息循环合作运行。

5.1 在win版本中,可以通过设置multi_threaded_message_loop为true的参数,开启浏览器多线程模式。能够和主应用的主消息循环并行处理运行。

wKgZO2juBI2AWC4ZAAPOsS4W7H4735.png

如图所示,win应用中,在main方法中需要开启主界面的消息循环,这里的消息循环就一直在UI主线程中运行,直到应用退出,消息循环主线程才会结束退出。

另外在cef的浏览器主进程中,也同时开启多线程消息循环,此时Browser独享自己的消息循环线程,和主消息循环互不影响,可以实时的收到界面的点击响应和显示web界面等。



5.2 在mac版本中,有两种cef消息循环方式

第一种:直接将主应用的消息循环设置为cef的消息循环,即所有的消息接收和传递,都在CefRunMessageLoop()中进行,此时cef的消息循环占据了主导地位,主界面的按钮点击等操作,都需要cef抛出并提交给主线程。

第二种:当mac中采用了Qt等框架时,它本身有自己的消息主循环,而cef在mac中无法再开启自己的消息主循环,也不支持采用多线程机制单独运行。因此采用了将cef消息循环嵌入到Qt的消息循环中的方式,相当于时间片分割方式,到了定时时间,去专门处理cef的事件响应。

wKgZPGjuBI6AB-GCAAS__6-3i5I697.png

主循环消息启动后,生命周期跟随主应用,一直到应用退出才会结束。此时定一个时间片分割,时间自定义,可以50帧也就是每隔20ms处理一次。

当定时周期到的时候,就执行cef的消息循环处理,在CefDoMessageLoopWork()中去处理cef的具体事件响应。

另外在cef本身的回调中,也可以使用onScheduleMessageLoopWork()中拿到事件,然后到cef事件循环中去处理。

这样主循环和cef自己的的循环,就不断运行起来,在用户使用时,感觉不到这个细微的延时差距,主界面和cef界面基本都是在同时响应。



六.窗口适配

在界面显示过程中,打开网页或者本地页面时,通常需要重新修改窗口尺寸。在不同的版本需要不同的处理方式:

功能 win mac
获取窗口id (CefWindowHandle)this->winId() (CefWindowHandle)this->winId()
改变窗口大小 ::MoveWindow(hwnd, rect.x(), rect.y(), rect.width(), rect.height(), true) [nsview setFrameSize:NSMakeSize(rect.width(), rect.height())]
获取窗口句柄 browser->GetHost()->GetWindowHandle() browser->GetHost()->GetWindowHandle() browser->GetHost()->GetOpenerWindowHandle()

表6.1 cef窗口适配

在创建一个浏览器窗口时,需要调用SetAsChild设置浏览器的子窗口,这里首先获取当前生成的窗口id,可以直接用CefWindowHandle来进行转换。

在重绘窗口大小的时候,需要移动窗口,调整高和宽,这里cef没有提供通用的方法,只能使用不同平台的原生方法,因此调用了操作系统的系统接口。

获取窗口可以直接使用cef内部封装好的GetWindowHandle,这个是通用的接口,需要在UI线程中调用,但是在一些特殊的web窗口中,需要使用GetOpenerWindowHandle来获取非pop窗口的句柄,从而操作窗口界面正常显示。



七.版本区分

7.1 操作系统版本区分可以直接使用开源库的方法:

win系统:Q_OS_WIN

mac系统:Q_OS_MAC

当需要区分使用不同操作系统的接口,或者调用对应系统的原生方法时,需要使用该宏定义进行区分处理。

7.2 cef版本区分,可以使用cef_version中的定义:

#define CEF_VERSION_MAJOR 106

#define CEF_VERSION_MINOR 1

#define CEF_VERSION_PATCH 0

#define CEF_COMMIT_NUMBER 2678

通常来说,若应用程序中,同时存在多个cef版本,比如89,106等,主要是主版本号不同,则直接判断CEF_VERSION_MAJOR的数值即可,另外的三个小版本可以不做过多关注,若大版本相同,则需要进行小版本的详细区分。

不同的cef大版本,接口基本是一样的,但是当相差几十个版本的cef库时,则会出现接口参数变更,或者名称变化,新增部分接口等差异点,则需要在不同版本进行对应的处理和适配。



结尾

使用cef在win和mac上用的同一套文件,利用Qt的宏定义对平台进行了区分,利用cef版本对不同版本进行兼容,因此同样的源代码文件,在两个平台都可以运行,不同的cef版本也可以同时运行,比较方便维护升级。

后续可以继续完善,形成更多不同的功能,并进一步拆分成独立的模块,让大家少走一些弯路。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Win
    Win
    +关注

    关注

    0

    文章

    69

    浏览量

    29276
  • Mac
    Mac
    +关注

    关注

    0

    文章

    1133

    浏览量

    55787
  • CEF
    CEF
    +关注

    关注

    0

    文章

    38

    浏览量

    18918
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    LS1043A MACMAC 是否可以设置内部RGMI延迟

    Dear NXP Support Team, 我有一个客户,它在 RGMII 接口之一的自定义基板使用 LS1043A,FPGA 通过 MACMAC 连接连接。 由于我
    发表于 06-04 06:46

    Mac 存储扩展省钱指南:ICY DOCK 苹果生态外接/内置适配方案

    苹果Mac系列设备性能强劲、生态稳定,是创意设计、影视后期、办公运维的主流设备,但原生存储短板十分突出:MacBook板载SSD无法后期升级,官方扩容溢价极高;MacStudio、MacPro桌面
    的头像 发表于 05-29 15:03 116次阅读
    <b class='flag-5'>Mac</b> 存储扩展省钱指南:ICY DOCK 苹果生态外接/内置<b class='flag-5'>适配</b>方案

    科普|MAC地址注册流程

    MAC地址注册流程MAC地址是分配给网络设备的唯一标识符。它是一个由48位二进制数组成的地址,通常以6个十六进制数字对表示,中间用冒号或连字符分隔开。MAC地址是在网络设备制造时,由硬件厂商将固化
    的头像 发表于 05-15 18:11 128次阅读
    科普|<b class='flag-5'>MAC</b>地址注册流程

    使用WIN10系统正常下载TMC-EvalSystem-3.11.1 项目及最新的API,无法正常构建项目怎么解决?

    。能够win系统下,CMD命令中查询到 gcc -v及make -v。由于对提供的TMC-EvalSystem-3.11.1及API不了解,排查不了问题。 在网上看到有一些解答,是Linux做的命令,
    发表于 05-08 06:59

    浅析激光焊膏电子互连领域中的应用

    激光焊膏作为一种先进的焊接材料,电子互连领域中展现出了显著的应用优势和广阔的发展前景。以下从激光焊膏的原理、优势、应用领域及发展趋势等方面,对其电子互连领域中的应用进行浅析
    的头像 发表于 04-29 09:15 180次阅读

    RK系列核心板+JL6110,国产交换机芯片适配指导

    的特性,成为国产化替代的理想选择。本文基于眺望电子RK3568核心板平台,详细记录JL6110交换机芯片的MAC-to-MAC适配全过程,涵盖设备树配置、驱动移植
    的头像 发表于 04-17 17:03 1159次阅读
    RK系列核心板+JL6110,国产交换机芯片<b class='flag-5'>适配</b>指导

    科普|什么是MAC地址、MAC码、OUI码、蓝牙串号

    点击上方蓝字关注我们第一问:MAC地址是什么?MAC地址(MediaAccessControlAddress),直译为媒体访问控制地址,也称为局域网地址(LANAddress),以太网地址
    的头像 发表于 04-16 11:07 529次阅读
    科普|什么是<b class='flag-5'>MAC</b>地址、<b class='flag-5'>MAC</b>码、OUI码、蓝牙串号

    深入解析NXP Freescale MAC7100微控制器家族硬件特性

    深入解析NXP Freescale MAC7100微控制器家族硬件特性 嵌入式汽车应用领域,NXP Freescale的MAC7100微控制器家族凭借其卓越的性能和丰富的功能,成为了众多工程师
    的头像 发表于 04-09 09:40 173次阅读

    Debian 没有通过 HDMI-VGA 适配器输出,怎么解决这个问题?

    我不明白[i]any通过 HDMI-VGA 适配 Debian 输出我的 VGA 屏幕(甚至看不到启动上的任何文本)。使用 Fedora 映像,它可以正常工作。 Fedora
    发表于 03-31 07:19

    毫欧科普:详解合金电阻电源适配的应用

    适配器输出电流的一致性。图2.电阻的电流采样与检测(二)限流保护与过载防护电源适配短路、负载异常等场景下,需快速限制电流峰值,防止电路烧毁,合金电阻的高功率承载能力与稳定限流特性可精准满足该需求
    发表于 01-26 15:09

    集特GM9-5602适配WIN7,共筑国产新算力

    随着信创产业推进,国产CPU平台普遍转向适配麒麟、统信UOS等国产操作系统。
    的头像 发表于 01-20 17:51 1384次阅读
    集特GM9-5602<b class='flag-5'>适配</b><b class='flag-5'>WIN</b>7,共筑国产新算力

    集特GM0-5602海光3350主板:国产芯强适配Win7系统稳定运行新选择

    处理器,主频3.0GHz,基于自主x86架构,多核性能强劲,满足Win7系统下多任务并行需求。 · ‌ 系统适配 ‌:通过驱动优化与内核调整,完美兼容Windows 7(64位),支持传统工业软件与办公应用无缝运行,降低信创场景迁移成本。 ‌ 工业级设计:严苛环境稳定运行
    的头像 发表于 12-11 15:25 1268次阅读
    集特GM0-5602海光3350主板:国产芯强<b class='flag-5'>适配</b>,<b class='flag-5'>Win</b>7系统稳定运行新选择

    以太网通讯FPGA的实现

    也需要一次应答确认数据收到,断开连接双方需要进行4次挥手。如图所示: 三、TCP/UDP协议实现 本开发板提供有以太网PHY芯片KSZ9031RNX, PHY发送数据的时候,接收
    发表于 10-30 07:45

    win7无法识别USB设备怎么解决?

    我现在有一个添加了CDC的FX3固件,该设备可以win10和win11正常工作,但在win7似乎并不能正确的识别设备,串口和USB设备都
    发表于 07-16 06:52

    同步电机失步浅析

    纯分享帖,需要者可点击附件免费获取完整资料~~~*附件:同步电机失步浅析.pdf【免责声明】本文系网络转载,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请第一时间告知,删除内容!
    发表于 06-20 17:42