C++自定义线程中创建 cef 对象

C++ create cef object in custom thread

本文关键字:cef 对象 创建 自定义 线程 C++      更新时间:2023-10-16

我想要创建一个javascript对象来将其传递给函数回调,如下所示:

void MyClass::ThreadTaskOnSuccess(CefRefPtr<CefV8Value> callback, CefRefPtr<CefV8Context> callbackCtxt)
{
    if (!CefCurrentlyOn(TID_UI))
    {
        // switch to UI thread
        CefPostTask(TID_UI, NewCefRunnableMethod(this, &NewDownloadObject::CreateTempDownloadOnSuccess, callback, callbackCtxt));
        return;
    }
    // String creation works perfect!
    // CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateString("test");
    // "Access violation" will be thrown
    CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateObject(NULL);
    executionResult->SetValue("size", CefV8Value::CreateInt(123), V8_PROPERTY_ATTRIBUTE_NONE);
    executionResult->SetValue("fileName", CefV8Value::CreateString("some name of file"), V8_PROPERTY_ATTRIBUTE_NONE);
    CefV8ValueList args;
    args.push_back(executionResult);
    CefRefPtr<CefV8Value> retval;
    CefRefPtr<CefV8Exception> exception;
    if (callback->ExecuteFunctionWithContext(callbackCtxt, callbackCtxt->GetGlobal(), args, retval, exception, false))
    {
        if (exception.get())
        {
            throw CFdmException(exception->GetMessage().c_str());
        }
        else
        {
            // Execution succeeded.
        }
    }
}

但是 CefV8Value::CreateObject(NULL( 总是返回 null 结果。我想发生这种情况是因为代码在自定义线程中运行,因为某些任务必须在特殊线程中执行。

我说的对吗?以及如何切换到 cef 线程以与 V8 引擎配合使用并与之同步?

我错了吗?为什么 V8 会创建一个空对象?

更新

我添加了 UI 线程切换。在那之后,我总是在 Hzmy 的静止中cef_v8value_create_object中出现"访问冲突读取位置"异常。

简而言之:您必须只能从有效线程访问 V8。

您可能会错过如何在客户端应用程序中使用 V8 JavaScript 集成 wiki 页面。

使用 CEF3 WebKit 和 JS 执行在单独的渲染器进程中运行。渲染器进程中的主线程被标识为 TID_RENDERER,所有 V8 执行都必须在此线程上进行。在浏览器和渲染器进程之间进行通信的 JS API 应使用异步回调进行设计。有关示例,请参阅 http://www.chromium.org/developers/design-documents/extensions/how-the-extension-system-works/api-pattern-design-doc。

chromiumembedded 文档包含以下内容:

因此,在使用javascript模型进行操作之前,您应该打开正确的连接。 如果 V8 当前不在上下文中,或者需要检索和存储对上下文的引用,则可以使用两种可用的 CefV8Context 静态方法之一。GetCurrentContext(( 返回当前正在执行 JS 的帧的上下文。GetEnteredContext(( 返回 JS 执行开始的帧的上下文。例如,如果帧 1 中的函数调用帧 2 中的函数,则当前上下文将是帧 2,输入的上下文将是帧 1。

数组、对象和函数只能创建、修改,如果是函数,则只有在 V8 在上下文中才能执行。如果 V8 不在上下文中,则应用程序需要通过调用 Enter(( 进入上下文,并通过调用 Exit(( 退出上下文。只应使用 Enter(( 和 Exit(( 方法:

  1. 在现有上下文之外创建 V8 对象、函数或数组时。例如,创建 JS 对象以响应本机菜单回调时。

  2. 在当前上下文以外的上下文中创建 V8 对象、函数或数组时。例如,如果源自 frame1 的调用需要修改 frame2 的上下文。

所以这就是为什么我无法创建对象但能够创建 js 字符串的原因。您还可以看到一般使用示例。

下面的代码解决了这个问题:

if (callbackCtxt.get() && callbackCtxt->Enter())
{
    CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(NULL);
    // call ExecuteFunctionWithContext and perform other actions
    callbackCtxt->Exit();
}