CEF开发:如何获取JavaScript代码中的变量值传递到C++变量
CEF JS变量回传C++实现方案
CEF完全支持将JavaScript上下文内的变量值提取到C变量中,直接调用CefFrame::ExecuteJavaScript属于单向执行逻辑,没有设计返回值接收通道,因此执行产生的局部变量不会自动同步到C侧,可通过以下两种成熟方案实现取值:
方案1:V8窗口绑定回调(适配同渲染进程取值场景)
这是适配你当前需求最轻量化的方案,核心逻辑是提前在JS上下文挂载C++实现的回调函数,JS侧拿到目标值后主动调用回调传参:
- 实现自定义
CefV8Handler类,重写Execute方法接收JS传入的参数 - 在渲染进程的上下文创建回调
OnContextCreated中,将C++方法绑定到JS的window全局对象 - 修改待执行的JS代码,拿到
rect.x后调用绑定好的全局函数传值 - C++侧在回调中解析参数,直接赋值给目标int变量
核心代码示例:
- 自定义V8回调处理器
class RectRecvHandler : public CefV8Handler { public: int* output_rect_x; explicit RectRecvHandler(int* rect_x_ptr):output_rect_x(rect_x_ptr) {} bool Execute(const CefString& func_name, CefRefPtr<CefV8Value> caller, const CefV8ValueList& args, CefRefPtr<CefV8Value>& ret_val, CefString& err) override { if (func_name == "sendRectToCpp" && args.size() >= 1 && args[0]->IsInt()) { *output_rect_x = args[0]->GetIntValue(); return true; } return false; } IMPLEMENT_REFCOUNTING(RectRecvHandler); };
- 上下文初始化阶段绑定函数到window
void CustomRenderHandler::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) { CefRefPtr<CefV8Value> global_obj = context->GetGlobal(); // 传入你要赋值的C++ int变量地址 CefRefPtr<CefV8Handler> recv_handler = new RectRecvHandler(&rect_x); CefRefPtr<CefV8Value> js_bind_func = CefV8Value::CreateFunction("sendRectToCpp", recv_handler); global_obj->SetValue("sendRectToCpp", js_bind_func, V8_PROPERTY_ATTRIBUTE_NONE); }
- 修改原有JS执行代码
frame->GetMainFrame()->ExecuteJavaScript( R"( const elem = document.getElementsByClassName("my_class")[0]; const rect = elem.getBoundingClientRect(); alert(rect.x + ":" + rect.y); // 调用绑定函数传值,rect.x为浮点数,先取整转成int window.sendRectToCpp(Math.round(rect.x)); )", "", 1);
方案2:CEF消息路由(适配跨进程取值场景)
如果你需要把渲染进程拿到的rect值传到浏览器进程的C++变量中,可以直接用CEF内置的消息路由器,不用手动写V8绑定:
- 初始化时配置
CefMessageRouterConfig,分别在浏览器进程、渲染进程注册路由实例 - JS侧拿到rect.x后调用
window.cefQuery发送异步消息,把值作为请求参数传入 - 浏览器进程重写
CefMessageRouterBrowserSide::Handler的OnQuery方法,解析参数即可拿到目标值
注意:
getBoundingClientRect()返回的坐标值是浮点数类型,传给C++int变量前必须在JS侧做取整转换,否则会出现参数类型不匹配、取值失败的问题。
内容的提问来源于stack exchange,提问作者Optimus1
相关产品推荐
相关产品推荐

