重要的概念

在开发基于CEF3的应用程序前,需要理解一些重要的底层概念。

1. C++封装

libcef库使用C开发,导出的是一个C API。工程libcef_dll_wrapper是对这些C API的封装,与libcef库一起发布。这些c++代码通过工具translator自动生成。直接使用C API中以参看UsingTheCAPI部分。

2. 进程

CEF3基于多进程运行。主进程处理窗口的创建、UI及网络访问,主进程也叫浏览器进程。这个进程通常也是应用程序进程,大多数的逻辑运行在此进程下。渲染进程管理Blink渲染及JavaScript的运行。部分程序逻辑,如JavaScript的绑定、DOM的访问,也运行在渲染进程中。默认的进程模型会为每一个不同的跳转点(协议+域名,如http://www.baidu.com)创建一个新的渲染进程。在需要的时候,会创建一些其他类型的进程,如gpu进程。

默认情况下,主程序进程会被创建多次,作为非浏览器进程使用。即通过命令行传入不同标记给CefExecuteProcess函数实现非浏览器进程的创建。如果主程序的exe非常大,初始化需要很长的时间,或者主程序不适合作为非浏览器进程使用,那么可以提供一个单独的exe给子进程使用。这个可以通过配置项CefSettings.browser_subprocess_path实现。

CEF3创建的进程通过IPC技术进行交互。浏览器进程及渲染进程可以来回发送异步消息进行通信。渲染进程中的JavaScriptIntegration可以导出异步API,而这些API由浏览器进程进行具体处理(JavaScriptIntegration in the render process can expose asynchronous APIs that are handled in the browser process.)。

3. 线程

CEF3中每个进程都运行了多个线程。完整的线程列表可以查看枚举cef_thread_id_t。以下列举一些常用的线程。

  • TID_UI
    浏览器进程的主线程,如果使用CefSettings.multi_threaded_message_loop=false来调用CefInitialize(),则此线程同就应用程序主线程是同一个。

  • TID_IO
    浏览器进程用来处理IPC及网络消息的线程。

  • TID_FILE*
    浏览器进程用来与文件系统打交道的线程。阻塞操作应该在此线程或由客户程序创建的CefThread中运行。

  • TID_RENDERER
    渲染进程中的主线程。所有的Blink及V8交互必须在此线程中执行。

由于CEF的多线程特性,使用消息传递或锁定来保护数据成员不受多线程的访问是很重要的。CefPostTask系列函数支持在线程之间进行简单的异步消息传递。有关更多信息,请参见“Posting Tasks”部分。

当前线程可以使用CefCurrentlyOn()函数来验证。CEF样例程序中使用了以下辅助宏来帮助验证当前执行的是期望的线程类型。这此宏定义在include/wrapper/cef_helpers.h。

#define CEF_REQUIRE_UI_THREAD() DCHECK(CefCurrentlyOn(TID_UI));
#define CEF_REQUIRE_IO_THREAD() DCHECK(CefCurrentlyOn(TID_IO));
#define CEF_REQUIRE_FILE_BACKGROUND_THREAD()\DCHECK(CefCurrentlyOn(TID_FILE_BACKGROUND));
#define CEF_REQUIRE_FILE_USER_VISIBLE_THREAD()\DCHECK(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
#define CEF_REQUIRE_FILE_USER_BLOCKING_THREAD()\DCHECK(CefCurrentlyOn(TID_FILE_USER_BLOCKING));
#define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER));

为了支持异步访问一块代码,CEF提供了base::Lock和base::AutoLock类型,定义在include/base/cef_lock.h中,示例如下:

// Include the necessary header.
#include "include/base/cef_lock.h"// Class declaration.
class MyClass : public CefBaseRefCounted {public:MyClass() : value_(0) {}// Method that may be called on multiple threads.void IncrementValue();private:// Value that may be accessed on multiple theads.int value_;// Lock used to protect access to |value_|.base::Lock lock_;IMPLEMENT_REFCOUNTING(MyClass);
};// Class implementation.
void MyClass::IncrementValue() {// Acquire the lock for the scope of this method.base::AutoLock lock_scope(lock_);// |value_| can now be modified safely.value_++;
}

4. 引用计数

CEF框架下所有的类实现继承于CefBase[RefCounted|Scoped]接口,所以的指针实例通过CefRefPtr进行管理,CefRefPtr是一个智能指针,通过调用AddRef()及Release()进行引用计数的管理。最简单的示例如下:

class MyClass : public CefBaseRefCounted {public:// Various class methods here...private:// Various class members here...IMPLEMENT_REFCOUNTING(MyClass);  // Provides atomic refcounting implementation.
};// References a MyClass instance
CefRefPtr<MyClass> my_class = new MyClass();

5. 字符串

CEF为字符串定义了自己的数据结构,原因如下:

  • libcef库与宿主程序可能使用不同的runtime库进行堆内存的管理。所有对象,包括字符串,需要使用相同的runtime库进行内存的创建与释放。
  • libcef库可以被编译支持不同字符类型的字符串(如UTF8,UTF16或者宽字符)。默认是UTF16,但你可以在cef_string.h修改,然后重新编译CEF来满足自己的需求。当使用宽字符时,要记住这会依赖具体的平台。

UTF16字符串的结构体:

typedef struct _cef_string_utf16_t {char16* str;  // Pointer to the stringsize_t length;  // String lengthvoid (*dtor)(char16* str);  // Destructor for freeing the string on the correct heap
} cef_string_utf16_t;

然后,起个别名如下:

typedef char16 cef_char_t;
typedef cef_string_utf16_t cef_string_t;

CEF提供了许多C API来操作字符串类型(mapped via #defines to the type-specific functions)。如下

  • cef_string_set
  • cef_string_clear
  • cef_string_cmp

CEF也提供了一些函数用于不同编码(ASCII, UTF8, UTF16及宽字符)字符串间的转换。具体可查看cef_string.h及cef_string_types.h。

C++下使用CefString来处理CEF的字符串会很方便。CefString提供了到std::string(UTF8)及std::wstring(宽字符)的自动转换。也可被用于对结构体类型cef_string_t的赋值。

  • 赋值或从std::string转换
std::string str = “Some UTF8 string”;// Equivalent ways of assigning |str| to |cef_str|. Conversion from UTF8 will occur if necessary.
CefString cef_str(str);
cef_str = str;
cef_str.FromString(str);// Equivalent ways of assigning |cef_str| to |str|. Conversion to UTF8 will occur if necessary.
str = cef_str;
str = cef_str.ToString();
  • 赋值或从std::wstring转换
std::wstring str = “Some wide string”;// Equivalent ways of assigning |str| to |cef_str|. Conversion from wide will occur if necessary.
CefString cef_str(str);
cef_str = str;
cef_str.FromWString(str);// Equivalent ways of assigning |cef_str| to |str|. Conversion to wide will occur if necessary.
str = cef_str;
str = cef_str.ToWString();
  • 字符串编码为ASCII时,可使用FromASCII()
const char* cstr = “Some ASCII string”;
CefString cef_str;
cef_str.FromASCII(cstr);
  • 一些结构体,如CefSettings,有一些cef_string_t成员。CefString可以简化它的赋值操作。
CefSettings settings;
const char* path =/path/to/log.txt”;// Equivalent assignments.
CefString(&settings.log_file).FromASCII(path);
cef_string_from_ascii(path, strlen(path), &settings.log_file);

6. 命令行参数

CEF3和Chromium的很多功能可以通过命令行参数来控制。这些参数的格式为"–some_argument[=optional_param]",这些参数通过CefExecuteProcess()和CefMainArgs结构体来传递给CEF。

  • 在调用CefInitialize()前,可将CefSettings.command_line_args_disabled设置为true来禁用命令行参数。
  • 在宿主程序中,可以通过重载函数CefApp::OnBeforeCommandLineProcessing()来传递命令行参数
  • 可以通过重载函数CefBrowserProcessHandler::OnBeforeChildProcessLaunch()来向子进程传递特定的命令行参数

可以查看shared/common/client_switches.cc的注释获取更详细的信息

参考

https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage.md#markdown-header-processes

CEF笔记:CEF重要的概念相关推荐

  1. tensorflow笔记:流程,概念和简单代码注释

    tensorflow是google在2015年开源的深度学习框架,可以很方便的检验算法效果.这两天看了看官方的tutorial,极客学院的文档,以及综合tensorflow的源码,把自己的心得整理了一 ...

  2. MySQL学习笔记01【数据库概念、MySQL安装与使用】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  3. vue学习笔记-03-浅谈组件-概念,入门,如何用props给组件传值?

    vue学习笔记-03-浅谈组件-概念,入门,如何用props给组件传值? 文章目录 vue学习笔记-03-浅谈组件-概念,入门,如何用props给组件传值? 什么是组件? 为什么要使用组件? 如何使用 ...

  4. CISAW风险管理学习笔记(2)-风险管理基本概念

    个人学习总结,CISAW学习笔记之风险管理基本概念:

  5. 2.SQL SERVER笔记——SQL SERVER系统概念

    2.SQL SERVER笔记--SQL SERVER系统概念 系统数据库 数据库管理员(DBA)的一项基本的技能是对SQL数据库引擎的系统数据库的深刻理解.数据库开发人员了解SQLSERVER自带的系 ...

  6. c语言注释语句执行吗,C语言学习笔记之C语言概念解析(附资料分享)每一个语句都必须以分号结尾但预处理命令函数头和花括号“}”之后不能加分号...

    [[怪兽爱C语言]C语言学习笔记之C语言概念解析(附资料分享)]https://toutiao.com/group/6582429294901854728/?iid=15906422033&a ...

  7. QML笔记:QML基本概念及使用

    QML笔记:QML基本概念及使用 Qt5中的Qt Qml和Qt Quick架构 Qt Qml模块本身并没有涉及图形显示,所有的图形处理都由Qt Quick模块完成. Qt Quick 以QPA(Qt ...

  8. Spring 笔记(一)概念梳理

    概念 预备知识 1. POJO POJO是Plain Old Java Object的缩写,是软件开发大师Martin Fowler提出的一个概念,指的是一个普通Java类.也就说,你随便编写一个Ja ...

  9. Angular学习笔记第一节 基本概念

    1.Let do it! ####1.ng的基础概念 在学习ng之前,我们只需要掌握HTML.CSS.JS即可. 简称ng.名字不错,吊! 重要的特性 有了ng,我们就可以轻松的构建SPA应用,而且n ...

最新文章

  1. 正则表达式简介及在C++11中的简单使用
  2. AD恢复(3)使用AD回收站
  3. Python 技术篇 - 文件的读取和写入
  4. SAP常见的几个接口技术的区别
  5. 各大计算机公司 笔试及面试 题目 - 人民搜索
  6. php怎么样sphinx,php使用sphinx
  7. oracle和mysql数据实时同步_异构数据源的CDC实时同步系统——最终选型实战
  8. 灯泡(信息学奥赛一本通-T1438)
  9. lintcode 627 最长回文串Python版本
  10. 【elasticsearch】 document 查询原理
  11. lsd 特征点匹配代码_OpenCvSharp 通过特征点匹配图片
  12. Activity/Fragment最强生命周期总结
  13. 《无线通信与网络》第二章 信号传输基础
  14. 获取APP包名和activity的几种方法
  15. HSQL调优的一些个人见解
  16. python视频教程唐学韬-python
  17. PaddlePaddle深度学习--线性回归
  18. 27个常用stata命令(2)
  19. 虚拟服务器跟目录,如何找虚拟主机根目录?
  20. 外汇和股票有什么区别啊?

热门文章

  1. word 中如何输入分数和指数
  2. 计算机入门及操作技能训练,计算机入门及操作技能训练.ppt
  3. caffe在窗口上不打印log信息
  4. 新天龙八部内测服务器维护,《新天龙八部》内测服务器更新家园萌宠初养成
  5. leetcode495:提莫攻击
  6. go锁屏 v5.07 安卓版
  7. android的访问存储权限,使用SAF(存储访问框架)的Android SD卡写权限
  8. 运营数据分析须掌握的十个经典方法
  9. 【ML】【HMM】【转】隐马尔可夫模型(HMM)简介
  10. Internet Explorer中的潘多拉魔盒   作者:江海 (转)