You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CEF环境下如何通过JavaScript调用C++回调函数?

可以将JS的alert()替换为调用C++函数,以下是具体实现方式

CEF支持JS与C的双向通信,主要通过**注入绑定C逻辑的自定义JS对象**,或者进程间消息传递两种方式实现,下面分别给出具体方案:

方案一:注入自定义JS对象(直接调用C++方法)

这种方式可以让JS直接调用绑定到全局对象的C++方法,步骤如下:

  1. 实现CefRenderProcessHandler类,重写OnContextCreated方法,在浏览器上下文初始化时注入自定义V8对象:
class MyRenderProcessHandler : public CefRenderProcessHandler {
public:
    void OnContextCreated(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
                          CefRefPtr<CefV8Context> context) override {
        // 获取全局window对象
        CefRefPtr<CefV8Value> globalObj = context->GetGlobal();

        // 创建自定义对象
        CefRefPtr<CefV8Value> bridgeObj = CefV8Value::CreateObject(nullptr, nullptr);

        // 绑定C++回调方法到自定义对象
        CefRefPtr<CefV8Handler> handler = new MyV8Handler();
        bridgeObj->SetValue("sendRectData", 
                           CefV8Value::CreateFunction("sendRectData", handler),
                           V8_PROPERTY_ATTRIBUTE_NONE);

        // 将自定义对象挂载到window下
        globalObj->SetValue("MyCppBridge", bridgeObj, V8_PROPERTY_ATTRIBUTE_NONE);
    }

    // 实现V8回调处理器
    class MyV8Handler : public CefV8Handler {
    public:
        bool Execute(const CefString& name,
                     CefRefPtr<CefV8Value> object,
                     const CefV8ValueList& arguments,
                     CefRefPtr<CefV8Value>& retval,
                     CefString& exception) override {
            if (name == "sendRectData" && arguments.size() == 2) {
                // 从JS参数中获取rect的x和y值
                double x = arguments[0]->GetDoubleValue();
                double y = arguments[1]->GetDoubleValue();

                // 这里编写你的C++业务逻辑,比如打印、存储或处理坐标
                printf("Received rect coordinates from JS: x=%.2f, y=%.2f\n", x, y);

                return true;
            }
            return false;
        }
    };

    IMPLEMENT_REFCOUNTING(MyRenderProcessHandler);
};
  1. 修改你的ExecuteJavaScript代码,将alert替换为调用自定义JS对象的方法:
(*frame).GetMainFrame()->ExecuteJavaScript(
    "const elem = document.getElementsByClassName(\"my_class\")[0];const rect = elem.getBoundingClientRect(); window.MyCppBridge.sendRectData(rect.x, rect.y);",
    "", 
    1
);

方案二:使用CEF进程间消息传递

如果你的C++逻辑运行在浏览器进程(而非渲染进程),可以通过消息传递实现:

  1. 在JS中调用cefQuery发送数据到渲染进程:
(*frame).GetMainFrame()->ExecuteJavaScript(
    "const elem = document.getElementsByClassName(\"my_class\")[0];const rect = elem.getBoundingClientRect();"
    "cefQuery({request: JSON.stringify({x: rect.x, y: rect.y}), onSuccess: ()=>{}, onFailure: ()=>{}});",
    "", 
    1
);
  1. 在CefRenderProcessHandler中处理JS发送的查询,并转发到浏览器进程:
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                              CefRefPtr<CefFrame> frame,
                              CefProcessId source_process,
                              CefRefPtr<CefProcessMessage> message) override {
    if (message->GetName() == "SendRectData") {
        // 从消息中获取坐标数据
        CefRefPtr<CefListValue> args = message->GetArgumentList();
        double x = args->GetDouble(0);
        double y = args->GetDouble(1);
        // 处理C++逻辑
        printf("Received rect coordinates: x=%.2f, y=%.2f\n", x, y);
        return true;
    }
    return false;
}

bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                    CefRefPtr<CefFrame> frame,
                    CefRefPtr<CefRequest> request,
                    bool user_gesture,
                    bool is_redirect) override {
    // 注册cefQuery回调
    frame->ExecuteJavaScript(
        "window.cefQuery = function(query) {"
        "  CefQuery({request: query.request, onSuccess: query.onSuccess, onFailure: query.onFailure});"
        "};",
        "",
        1
    );
    return false;
}

注意事项

  • CEF分为渲染进程和浏览器进程,V8对象绑定操作必须在渲染进程的主线程中执行;如果C++逻辑涉及UI操作,建议放在浏览器进程中处理,通过进程间消息传递数据。
  • 确保在CEF初始化时设置自定义的CefRenderProcessHandler,否则注入或消息监听不会生效。

内容的提问来源于stack exchange,提问作者Optimus1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:27:17