前面我们学习了C++和JS的基本交互。例如C++调用js。
browser->GetMainFrame()->ExecuteJavaScript(js, L"", 0); 但是在实际应用过程中可能我们事先并不知道函数原型,而是使用的函数指针来回调结果。例如:
do_event(call_back,parama1,parama2,....paramaN) 此时需要使用CEF::ExecuteFunction 和ExecuteFunctionWithContext()方法执行JS函数。ExecuteFunction()方法只允许用在V8中,且V8在“使用上下文”所描述的上下文中。ExecuteFunctionWithContext()方法允许应用程序指定即将执行的上下文。
下面我们将实现一个最简单的回调模型:注册+回调。
步骤:
- CefV8Handler实现register
- 保存Callback的上下文
- 进入上下文调用回调
- 执行完退出上下文
//Render进程注册回调函数 void CRenderApp::OnWebKitInitialized() { CEF_REQUIRE_RENDERER_THREAD(); // Define the extension contents. std::string extensionCode = "var MyMath;" "if (!MyMath)"//如果没有MyMath对象,则定义一个MyMath对象 " MyMath = {};" "(function() {" " MyMath.register = function(call_back) {"//定义一个MyMath的add函数 " native function register(call_back);" " return register(call_back);"//add在CefV8Handler具体实现 " };" " MyMath.hellow = 'Hello JS!';"//定义一个MyMath的成员变量 "})();"; CefRefPtr<CefV8Handler> add_handler = new CJSHandler(this); // Register the extension. CefRegisterExtension("v8/test", extensionCode, add_handler); } //实现注册函数 bool CJSHandler::Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) { //callback register if (name == "register") { if (arguments.size() == 1 && arguments[0]->IsFunction()) { CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext(); CefRefPtr<CefV8Value> call_back = arguments[0]; //由于这里只是一个demo,所以把funcid固定为1,如果存在多个注册回调函数,请维护funcid和callback的关系 //if (m_render_app) // m_render_app->AddCallBack(1, context, call_back); //调用回调,进入上下文 context->Enter(); CefV8ValueList call_arguments; call_arguments.push_back(CefV8Value::CreateString(_T("hellow word"))); //调用回调函数,回调参数 call_back->ExecuteFunction(NULL, call_arguments); //退出上下文 context->Exit(); return true; } } // return false; } 结果:

当然我这里事实是最简单的一个demo,在实际过程中我们应该将call_back和call_context保存起来,当结果处理完成之后执行回调。
typedef std::map<int32, std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value> > > CallbackMap; 正常的工作流程:
- 注册=》添加回调到map(map存在render进程中)
- js触发事件(事件投递到Browser进程处理或者自己直接处理)
- 处理完成(如果投递到Browser进程处理,则处理完成之后投递到Render进程)调用回调
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("test"); browser->SendProcessMessage 参考文档:
https://github.com/fanfeilong/cefutil/tree/master/doc
https://github.com/fanfeilong/cefutil/blob/master/doc/content_register_v8_extension.md
文章来源: https://blog.csdn.net/CAir2/article/details/91576805