QT:CEF实现js函数与C++函数的异步调用

1.CEF3使用多进程模式,Browser与Render分别处于两个独立进程之中;一般而言,Browser进程与我们的窗口进程一致,Render进程是一个独立的进程。

2.Browser进程和Render进程都包含browser和frame对象;

3.在CEF提供的例子中,主要是通过继承CefV8Handler,实现其

bool CefV8HandlerEx::Execute(const CefString &name,
                             CefRefPtr<CefV8Value> object,
                             const CefV8ValueList &arguments,
                             CefRefPtr<CefV8Value> &retval,
                             CefString &exception)

方法来实现js对C++函数的调用。

如果这个函数调用是一个简单的调用,即当函数调用发生时,如果我们能够快速的返回结果,那么我们可以通过更改retval的值来返回函数调用结果。

因为这个函数调用是发生在Render进程中的,如果函数调用时,我们想获取Browser进程内的信息,那我们就需要通过进程间通讯(方式:调用Frame的SendProcessMessage(PID_Browser,msg))告诉Browser进程,但是此时的问题就是,进程间通讯是个异步操作,我们无法通过这个方式获得结果,所以会导致整个调用不再是连续的,因此js函数调用的结果将不可知,那该如何解决?

我们可以借助于js的异步调用来完成这一点,具体的思路如下:

1.js发起函数调用Func(需要注意这个Func是需要在Render_App的OnContextCreated方法中绑定到Context上,具体可参考https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md#markdown-header-window-binding,且有一个CefV8Handler与Func绑定),这个Func传递一个回调函数(callback)作为参数;

2.Render进程中的CefV8Handler的Execute检测到该函数,取得callback参数,将其放入到函数调用缓存中,可以参考https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage.md#markdown-header-asynchronous-javascript-bindings

3.发送一个进程间消息告诉Browser进程,Browser进程需要实现OnProcessMessageReceived方法。Browser接受到该消息以后,完成相应的操作,并发送一个进程间消息告诉Render进程,Render进程同样也需要实现OnProcessMessageReceived方法;

4.Render进程接受到特定消息以后,检索出message中包含的参数信息,并从函数调用缓存中查找特定的callback函数;

5.当从在对应的callback时,调用该callback

6.js在Func中传递的callback中接收参数信息,并完成后续工作。

需要注意的是:

1.这个RenderApp进程,如果在加载的page中存在多个iframe,则这个OnContextCreated会被调用多次,如果不想再每个iframe中注册这个Func函数,则将其写入OnWebKitInitialed中,这个也是Render的一个接口。

2.如果存在多个iframe,并不在同一个域,则有可能会出现有些iframe无法接收消息的情况;

3.CefV8Handler最好实在RenderAPP的构造中初始化一次,不然在存在多个iframe的情况下,可能会出现函数缓存为空的情况,具体原因未知。

原文地址:https://www.cnblogs.com/chyshx/p/14519043.html