- 1.C++ 包装器
- 2.进程
- 3.线程
- 4.引用计数
- 5.字符串
- 6.作者答疑
libcef 共享库导出一个C API,将用户与 CEF运行时和代码库隔离开来。libcef_dll_wrapper 项目作为二进制版本的一部分以源代码形式分发,将这个导出的 C API 包装在 C++ API 中,然后链接到客户端应用程序。这个 C/C++ API 翻译层的代码是由翻译工具自动生成的。UsingTheCAPI页面描述了 C API 的直接使用。
2.进程CEF3 使用多个进程运行。处理窗口创建、绘制和网络访问的主要进程称为“浏览器”进程。这通常与宿主应用程序的进程相同,并且大部分应用程序逻辑将在浏览器进程中运行。界面渲染和 JavaScript 执行发生在单独的“渲染”进程中。一些应用程序逻辑,例如 JavaScript 绑定和 DOM 访问,也会在渲染进程中运行。默认流程模型将为每个唯一的来源(方案 + 域)生成一个新的渲染进程。其他进程将根据需要产生,例如处理Flash 等插件的“插件”进程和处理加速合成的“gpu”进程。
默认情况下,主应用程序可执行文件将多次生成以表示单独的进程。这是通过传递到 CefExecuteProcess 函数的命令行标志来处理的。 如果主应用程序可执行文件很大,需要很长时间才能加载,或者不适合非浏览器进程,则主机可以为那些其他进程使用单独的可执行文件。这可以通过 CefSettings.browser_subprocess_path 变量进行配置。有关详细信息,请参阅“应用程序结构”部分。
CEF3 产生的独立进程使用进程间通信 (IPC) 进行通信。在浏览器和渲染进程中实现的应用程序逻辑可以通过来回发送异步消息进行通信。渲染进程中的JavaScriptIntegration可以公开在浏览器进程中处理的异步 API。有关更多信息,请参阅“进程间通信”部分。
平台特定的调试技巧也适用于Windows、MacOS和Linux。
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 系列函数支持线程之间简单的异步消息传递。有关更多信息,请参阅“发布任务”部分。
可以使用 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_THREAD() DCHECK(CefCurrentlyOn(TID_FILE));
#define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER));
为了支持对代码块的同步访问,CEF 通过include/base/cef_lock.h头文件提供了 base::Lock 和 base::AutoLock 类型。例如:
// Include the necessary header.
#include "include/base/cef_lock.h"
// Class declaration.
class MyClass : public CefBase
{
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.引用计数
所有框架类都实现了 CefBase 接口,所有实例指针都使用 CefRefPtr 智能指针实现来处理,该实现通过调用 AddRef() 和 Release() 自动处理引用计数。 实现这些类的最简单方法如下:
class MyClass : public CefBase
{
public:
// Various class methods here...
private:
// Various class members here...
IMPLEMENT_REFCOUNTING(MyClass); // Provides atomic refcounting implementation.
};
// References a MyClass instance
CefRefPtr my_class = new MyClass();
5.字符串
CEF 定义了自己的数据结构来表示字符串。这是出于几个不同的原因:
- libcef 库和宿主应用程序可能使用不同的运行时来管理堆内存。所有对象,包括字符串,都需要使用分配内存的相同运行时来释放。
- 可以编译 libcef 库以支持不同的底层字符串类型(UTF8、UTF16 或宽)。默认为 UTF16,但可以通过修改cef_string.h 中的定义并重新编译 CEF来更改。选择宽类型时,请记住,尺寸会因平台而异。
对于 UTF16,字符串结构如下所示:
typedef struct _cef_string_utf16_t
{
char16 *str; // Pointer to the string
size_t length; // String length
void (*dtor)(char16 *str); // Destructor for freeing the string on the correct heap
} cef_string_utf16_t;
然后将选定的字符串类型 typedef 为泛型类型:
typedef char16 cef_char_t;
typedef cef_string_utf16_t cef_string_t;
CEF 提供了许多用于操作 CEF 字符串类型的 C API 函数(通过 #defines 映射到特定于类型的函数)。例如:
- cef_string_set会在复制或不复制值的情况下为结构分配一个字符串值。
- cef_string_clear将清除字符串值。
- cef_string_cmp将比较两个字符串值。
CEF 还提供用于在所有支持的字符串类型(ASCII、UTF8、UTF16 和宽)之间进行转换的函数。有关完整的函数列表,请参阅cef_string.h和cef_string_types.h标头。
CefString 类简化了 C++ 中 CEF 字符串的使用。CefString 提供与 std::string (UTF8) 和 std::wstring (wide) 类型之间的自动转换。它还可以用于包装现有的 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.作者答疑
如有疑问,请留言。