CEF(Chromium Embedded Framework)下载以及编译目的为了后续与DuiLib相结合

1、CEF的介绍

Chromium Embedded Framework(CEF) 是一个开源软件框架,用于在另一个应用程序中嵌入Chromium web浏览器。这使开发人员能够向其应用程序中添加web浏览功能,并能够使用HTML、CSS和JavaScript创建应用程序的用户界面(或只是其中的一部分)。

CEFLinuxmacOSWindows上运行。它有许多语言绑定,包括C、C++、Go、Java和Python

1.1、概述

Chromium嵌入式框架有两个版本:CEF 1CEF 3Chromium Content API出现后,CEF 2的开发被放弃。

CEF 1是基于Chromium WebKit API的单进程实现。它不再得到积极开发或支持。

CEF 3是基于Chromium Content API的多进程实现,其性能类似于Google Chrome。它使用异步消息传递在主应用程序进程和一个或多个渲染进程(Blink+V8 JavaScript引擎)之间进行通信。它支持内部(PDF查看器)或外部可加载的PPAPI插件和扩展。不支持单进程运行模式,但仍存在;当前仅用于调试目的。

2019年3月16日,CEF 版本号随着 CEF 73.1.3 + g46cf800 + chromium-73.0.3683.75的发布而改变。之前在2019年3月14日发布的版本是 CEF 3.3683.1920.g9f41a27。这两个版本都是基于 Chromium 73.0.3683.75,但是新版本编号的主要编号与它所基于的 Chromium 主要版本号相同。

CEF附带了一个名为CefClient的示例应用程序,该应用程序使用WinAPICocoaGTK(取决于平台)用C**++编写,并包含各种功能的演示。较新版本包括一个名为CefSimple的示例应用程序,该应用程序以及附带的教程演示了如何使用CEF 3**创建简单应用程序。

文档可以在位于include目录的头文件和wiki页面上找到。
在这里插入图片描述

2、CEF的作用

CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目。Google Chromium项目主要是为Google Chrome应用开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器支持CEF作用是在客户端嵌入网页界面

  • 嵌入一个兼容HTML5的浏览器控件到一个已经存在的本地应用。
  • 创建一个轻量化的壳浏览器,用以托管主要用Web技术开发的应用。
  • 有些应用有独立的绘制框架,使用CEF对Web内容做离线渲染。
  • 使用CEF做自动化Web测试。

3、CEF的下载和编译

首先CEF的所有版本:所有版本
在这里插入图片描述
获取更多:
在这里插入图片描述

CEF自动构建了多个平台多个版本,这里选择Windows 64位平台的Standard Distribution文件。我下载的是这个版本:CEF下载
在这里插入图片描述
解压出来里面有这些文件(build)是我自己创建的:

不同平台拥有共同的结构,介绍一下Standard Distribution版本的文件夹结构:

  • cmake: 包含所有目标共享的CMake配置文件。
  • Debug: 包含 libcef.dll、 libcef.lib 和构建运行基于 CEF 的应用程序所需的其他组件的调试版本。默认情况下,这些文件应该放在与可执行文件相同的目录中,并作为构建过程的一部分复制到那里。CEF动态库(libcef.dll on Windows, libcef.so on Linux, “Chromium Embedded Framework.framework” on OS X)
  • include: 包含所有必需的CEF头文件。
  • libcef_dll: 包含libcef_dll_wrapper静态库的源代码,所有使用CEF C++API的应用程序都必须链接该库。
  • Release: 同Debug。包含 libcef.dll、 libcef.lib 和其他需要构建并运行基于CEF 的应用程序的发布版本
  • Resources: 包含 libcef.dll 所需的资源
  • tests: 演示CEF的用法demo及测试用例等。

每个二进制压缩包里包含一个README.txt文件和一个LICENSE.txt文件,README.txt用以描述平台相关的细节,而LICENSE.txt包含CEF的BSD版权说明。如果你发布了基于CEF的应用,则应该在应用程序的某个地方包含该版权声明。

3.1、基本文件结构

├─cmake
├─Debug
├─include
│  ├─base
│  │  └─internal
│  ├─capi
│  │  ├─test
│  │  └─views
│  ├─internal
│  ├─test
│  ├─views
│  └─wrapper
├─libcef_dll
│  ├─base
│  ├─cpptoc
│  │  ├─test
│  │  └─views
│  ├─ctocpp
│  │  ├─test
│  │  └─views
│  └─wrapper
├─Release
├─Resources
│  └─locales
└─tests
    ├─cefclient
    │  ├─browser
    │  ├─common
    │  ├─renderer
    │  └─resources
    │      ├─extensions
    │      │  └─set_page_color
    │      └─win
    ├─cefsimple
    │  └─res
    ├─ceftests
    │  ├─extensions
    │  ├─resources
    │  │  ├─net
    │  │  │  └─data
    │  │  │      └─ssl
    │  │  │          └─certificates
    │  │  └─win
    │  └─views
    ├─gtest
    │  ├─include
    │  │  └─gtest
    │  ├─src
    │  └─teamcity
    │      ├─include
    │      └─src
    └─shared
        ├─browser
        ├─common
        ├─renderer
        └─resources

  • cmake:包含所有目标共享的CMake配置文件

  • Debug:包含构建和运行基于CEF的应用程序的调试版本所需的libcef.dll、libcef.lib和其他组件。默认情况下,这些文件应该与可执行文件放在同一目录中,并将作为构建过程的一部分复制到那里。

  • include:包含所有必需的CEF头文件。

  • libcef_dll:包含libcef_dll_wrapper静态库的源代码,所有使用CEF C++API的应用程序都必须链接该库。

  • Release:包含libcef.dll、libcef.lib和其他必需的组件构建并运行基于CEF的应用程序的发布版本。通过默认情况下,这些文件应与可执行文件,并将作为构建过程的一部分复制到那里。

Resources:包含libcef.dll所需的资源。默认情况下,这些文件应与libcef…dll放在同一目录中,并将作为构建过程的一部分复制到那里。

  • tests/ 演示 CEF 用法的测试目录。

  • cefclient:包含配置为使用此发行版中的文件生成的 cefclient 示例应用程序。此应用程序演示了各种 CEF 功能。

  • cefsimple:包含配置为使用此发行版中的文件生成的 cefsimple 示例应用程序。此应用程序演示了创建浏览器窗口所需的最少功能。

  • ceftests:包含执行CEF API的单元测试。

  • gtest:包含ceftests目标使用的Google C++测试框架。

  • shared:包含由cefclient和ceftests目标共享的源代码。

在这里插入图片描述
使用cmake编译,我这里使用的是Visual Studio 2019编译,x64版本
在这里插入图片描述
在这里插入图片描述
一共有7个项目:
在这里插入图片描述

  • ALL_BUILDZERO_CHECK:是cmake自动生成的辅助工程。
  • cef_gtestceftests:都是测试模块
  • cefclient:一个包含CEF各种API演示的浏览器程序Demo。
  • cefsimple:一个简单的CEF浏览器程序Demo。
  • libcef_dll_wrapper:对libcef库的C++代码封装。上述cefclient与cefsimple都会用它。
    在这里插入图片描述
    等待一会儿,然后程序就执行起来了,默认打开的是谷歌首页,如果打开的空白,是因为无法访问谷歌导致的。
    在这里插入图片描述
    可以直接在VS中搜索www.google.com去更改代码,发现它在cefclient-browser-main_context_impl.cc文件里,把它改为www.baidu.com再运行就正常了。
    在这里插入图片描述
    在这里插入图片描述
    cefsimple同理,在cefsimple->simpleapp.cc里:
  url = command_line->GetSwitchValue("url");
  if (url.empty())
    url = "http://www.baidu.com";

3.2、发布文件目录结构

即发布之后的可执行文件所在目录含有的文件:

│  chrome_100_percent.pak
│  chrome_200_percent.pak
│  chrome_elf.dll
│  d3dcompiler_47.dll
│  debug.log
│  icudtl.dat
│  libcef.dll
│  libEGL.dll
│  libGLESv2.dll
│  resources.pak
│  snapshot_blob.bin
│  tree.txt
│  v8_context_snapshot.bin
│  vk_swiftshader.dll
│  vk_swiftshader_icd.json
│  vulkan-1.dll
│      
└─locales
        af.pak
	    ...
        zh-CN.pak

在这里插入图片描述

3.3、必需组件

没有它们,CEF将无法运作。

  • libcef.dll: CEF核心库。
  • chrome_elf.dll: 崩溃报告库。
  • icudtl.dat: Unicode支持数据。
  • snapshot_blob.bin: V8快照数据。
  • v8_context_snapshot.bin: V8快照数据。
    在这里插入图片描述

3.4、可选组件

以下组件是可选的。如果它们丢失,CEF将继续运行,但任何相关功能都可能损坏或禁用。

3.4.1、本地化资源

使用CefSettings.pack_loading_disabled可以完全禁用区域设置文件加载。可以使用CefSettings.locales_dir_path自定义区域设置目录路径。

locales/:包含CEF、Chromium和Blink使用的本地化资源的目录。根据CefSettings.locae值从该目录加载一个.pak文件。只需要分发已配置的区域设置。如果未配置区域设置,则将使用默认的区域设置“en-US”。如果没有这些文件,任意Web组件可能会显示错误。

3.4.2、其他资源

使用CefSettings.Pack_loading_disabled可以完全禁用包文件加载。可以使用CefSettings.resources_dir_path自定义资源目录路径。

  • chrome_100_percent.pak。
  • chrome_200_percent.pak。
  • resources.pak。
    在这里插入图片描述

这些文件包含CEFChromiumBlink使用的非本地化资源。如果没有这些文件,任意Web组件可能会显示错误。

3.4.3、Direct3D 支持
  • d3dcompiler_47.dll。

支持GPU加速渲染HTML5内容,如2D画布、3D CSSWebGL。如果没有此文件,当启用GPU加速时(大多数情况下为默认设置),上述功能可能会失败。建议使用此捆绑版本,而不是依赖可能旧的、未经测试的系统安装版本。
在这里插入图片描述

3.5.4、ANGLE支持
  • libEGL.dll。
  • libGLESv2.dll。

支持渲染HTML5内容,如2D画布、3D CSSWebGL。如果没有这些文件,上述功能可能会失败。
在这里插入图片描述

3.4.5、SwANGLE 支持
  • vk_swiftshader.dll。
  • vk_swiftshader_icd.json。
  • vulkan-1.dll。

支持使用SwiftShaderVulkan库作为ANGLEVulken后端对HTML5内容(如2D画布、3D CSS和WebGL)进行软件渲染。如果没有这些文件,当GPU加速被禁用或不可用时,上述功能可能会失败。
在这里插入图片描述

来源于分发包内README.txt

3、编译libcef_dll_wrapper

其实最重要的libcef_dll_wrapper是不是发现还没编译,当然不是,我们在编译cefclient的时候,就顺带编译了。生成debug路径:

D:\cethree\cef_binary_105.3.37+g4445dc6+chromium-105.0.5195.102_windows64\build\libcef_dll_wrapper\Debug

在这里插入图片描述
release路径:
在这里插入图片描述
我们也可以查看项目,会发现这个库早已经在项目属性里设置好了。
在这里插入图片描述

4、CEF结构

4.1、 CEF进程和窗口之间的结构关系

一个浏览器有很多个CefBrowser窗口,这些窗口都是在Browser进程中创建。browser进程用来管理和处理回调函数消息。Renderer进程用来实现网页的渲染,每个renderer进程包含有一个主网页mainframe和多个子网页subframe
在这里插入图片描述

4.2、 Renderer进程的实现结构

renderer程序继承CefAppCefRenderProcessHandler类,在main函数中初始化。通过CefSettings.browser_subprocess_path配置render可执行程序路径。browser进程就会去启动这个进程去渲染网页。
在这里插入图片描述

4.3、browser进程的实现结构

browserapp要继承CefAppCefBrowserProcessHandler类。实现browserapp的定义。同时要新建clienthandler类实现图中的回调函数接口类,用来处理拦截响应请求、管理生命周期、下载、显示加载、右键菜单等。在mian函数中初始化、启动消息循环。调用CefBrowserHost的静态方法创建browser窗口对象,在render进程的Frame中加载渲染内容。
在这里插入图片描述

4.4、CEF多进程和多线程

4.4.1、 进程

CEF3是多进程架构的,CEF3进程主要有一个Browser(浏览器)进程和多个Renderer(渲染)进程。Browser被定义为主进程,负责窗口管理,网络请求,网页管理 、网络交互。browser从服务器器请求到了响应,将html文本发送给Renderer 进程,render进程加载html,进行渲染,展示网页的内容;除此之外,Renderer进程还负责Js Binding和对Dom节点的访问。

BrowserRenderer进程可以通过发送异步消息进行双向通信。主应用程序很大,加载时间比较长,或者不能在非浏览器进程里使用,则宿主程序可使用独立的可执行文件去运行这些Renderer进程。这可以通过配置CefSettings.browser_subprocess_path变量做到。

4.4.2、 线程

Browser进程中包含如下主要的线程:

  • TID_UI 线程是浏览器的主线程。如果应用程序在调用调用CefInitialize()时,传递CefSettings.multi_threaded_message_loop=false,这个线程也是应用程序的主线程。
  • TID_IO 线程主要负责处理IPC消息以及网络通信。
  • TID_FILE 线程负责与文件系统交互。

4.5、网页嵌入应用程序代码构成和实例

每个CEF3应用程序都是相同的结构

  • 提供入口函数,用于初始化CEF、运行子进程执行逻辑或者CEF消息循环。
  • 提供CefApp实现,用于处理进程相关的回调。
  • 提供CefClient实现,用于处理Browser实例相关的回调。
  • 执行CefBrowserHost::CreateBrowser()创建一个Browser实例,使用CefLifeSpanHandler管理Browser对象生命周期。
4.5.1、 入口函数

需要在程序的入口函数执行cef对象创建,初始化,命令行参数解析,CEF属性设置,和CEF消息循环开启等。CEF需要启动一个主进程来管理网页见面。这个主进程就是在man函数中启动,进入消息循环,直到程序结束,才退出main函数。

4.5.2、CEF单实例进程

单例进程模式就是CEF的启动,网页的打开都在:

int main(int argc, char* argv[]) {

  // Structure for passing command-line arguments.

  // The definition of this structure is platform-specific.

  CefMainArgs main_args(argc, argv);

 

  // Optional implementation of the CefApp interface.

  CefRefPtr<MyApp> app(new MyApp);

 

  // Execute the sub-process logic, if any. This will either return immediately for the browser

  // process or block until the sub-process should exit.

  int exit_code = CefExecuteProcess(main_args, app.get());

  if (exit_code >= 0) {

    // The sub-process terminated, exit now.

    return exit_code;

  }

 

  // Populate this structure to customize CEF behavior.

  CefSettings settings;

 

  // Initialize CEF in the main process.

  CefInitialize(main_args, settings, app.get());

 

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is called.

  CefRunMessageLoop();

 

  // Shut down CEF.

  CefShutdown();

 

  return 0;

}

4.5.3、主子进程的模式

主进程和子进程分开的模式,主进程运行browser进程,网页加载放在子进程render进程中。这是需要创建两个进程和两个主函数。

主进程程序的入口函数:

// Program entry-point function.

// 程序入口函数

int main(int argc, char* argv[]) {

	  // Structure for passing command-line arguments.
	
	  // The definition of this structure is platform-specific.
	
	  // 传递命令行参数的结构体。
	
	  // 这个结构体的定义与平台相关。
	
	  CefMainArgs main_args(argc, argv);
	
	 
	
	  // Optional implementation of the CefApp interface.
	
	  // 可选择性地实现CefApp接口
	
	  CefRefPtr<MyApp> app(new MyApp);

 

	  // Populate this structure to customize CEF behavior.
	
	  // 填充这个结构体,用于定制CEF的行为。
	
	  CefSettings settings;
	
	 
	
	  // Specify the path for the sub-process executable.
	
	  // 指定子进程的执行路径
	
	  CefString(&settings.browser_subprocess_path).FromASCII(/path/to/subprocess”);
	
	 
	
	  // Initialize CEF in the main process.
	
	  // 在主进程中初始化CEF
	
	  CefInitialize(main_args, settings, app.get());

 

	  // Run the CEF message loop. This will block until CefQuitMessageLoop() is called.
	
	  // 执行消息循环,此时会堵塞,直到CefQuitMessageLoop()函数被调用。
	
	  CefRunMessageLoop();
	
	 
	
	  // Shut down CEF.
	
	  // 关闭CEF
	
	  CefShutdown();
	
	 
	
	  return 0;

}

子进程程序入口函数:

// Program entry-point function.

// 程序入口函数

int main(int argc, char* argv[]) {

	  // Structure for passing command-line arguments.
	
	  // The definition of this structure is platform-specific.
	
	  // 传递命令行参数的结构体。
	
	  // 这个结构体的定义与平台相关。
	
	  CefMainArgs main_args(argc, argv);

 

	  // Optional implementation of the CefApp interface.
	
	  // 可选择性地实现CefApp接口
	
	  CefRefPtr<MyApp> app(new MyApp);
	
	 
	
	  // Execute the sub-process logic. This will block until the sub-process should exit.
	
	  // 执行子进程逻辑,此时会堵塞直到子进程退出。
	
	  return CefExecuteProcess(main_args, app.get());

}

  • 22
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

森明帮大于黑虎帮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值