美文网首页
CEF之c++与JS交互

CEF之c++与JS交互

作者: 晓函 | 来源:发表于2018-08-17 19:46 被阅读201次

首先定义CCefClientApp类,继承CefApp,CefBrowserProcessHandler,CefRenderProcessHandler,并实现相关接口

//CefClientApp.h
class CCefClientApp : public CefApp, public CefBrowserProcessHandler, CefRenderProcessHandler
{
public:
    CCefClientApp();
    ~CCefClientApp();


    //所有的CEF接口 都需要重载GetXXXHandler,并且return this,才会有效
    virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return this; }

    //===========CefRenderProcessHandler
    virtual void OnWebKitInitialized() override;

private:
    CefRefPtr<CCEFV8HandlerEx> v8Handler_;
    // Include the default reference counting implementation.
    IMPLEMENT_REFCOUNTING(CCefClientApp);

private:

};

//CefClientApp.cpp

void CCefClientApp::OnWebKitInitialized()
{
    //MessageBox(NULL,L"OnWebKitInitialized\n",0,0);
    std::string app_code =
        //-----------------------------------
        //声明JavaScript里要调用的Cpp方法
        "var app;"
        "if (!app)"
        "  app = {};"
        "(function() {"

        //  jsInvokeCPlusPlus 实例函数
        "  app.jsInvokeCPlusPlus = function(v1, v2) {"
        "    native function jsInvokeCPlusPlus();"
        "    return jsInvokeCPlusPlus(v1, v2);"
        "  };"

        //函数
        "  app.jsTransform = function(v1) {"
        "    native function jsTransform();"
        "    return jsTransform(v1);"
        "  };"

        "})();";


    // Register app extension module

    // JavaScript里调用app.jsInvokeCPlusPlus时,就会去通过CefRegisterExtension注册的CefV8Handler列表里查找
    // 找到"v8/app"对应的CCEFV8HandlerEx,就调用它的Execute方法
    // 假设v8Handler_是CCefClientApp的一个成员变量
    //v8Handler_ = new CCEFV8HandlerEx();

    CefRegisterExtension("v8/app", app_code, v8Handler_);

}

定义V8HandlerEx

//CEFV8HandlerEx.h

class CCEFV8HandlerEx : public CefV8Handler {
public:
    CCEFV8HandlerEx();
    ~CCEFV8HandlerEx();
public:
    virtual bool Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) override;
private:
    // Map of message callbacks.
    typedef std::map<std::pair<std::string, int>, std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value> > >CallbackMap;
    CallbackMap callback_map_;


public:
    IMPLEMENT_REFCOUNTING(CCEFV8HandlerEx);
};

//CEFV8HandlerEx.cpp

//JS调用C++函数的回调
bool CCEFV8HandlerEx::Execute(const CefString& name  /*JavaScript调用的C++方法名字*/, CefRefPtr<CefV8Value> object /*JavaScript调用者对象*/, const CefV8ValueList& arguments /*JavaScript传递的参数*/, CefRefPtr<CefV8Value>& retval /*返回给JS的值设置给这个对象*/, CefString& exception/*通知异常信息给JavaScript*/)
{
    if (name == _T("jsInvokeCPlusPlus"))
    {
        if (arguments.size() == 2)
        {
            CefString strParam1 = arguments.at(0)->GetStringValue();
            CefString strParam2 = arguments.at(1)->GetStringValue();

            TCHAR szBuffer[512];
            StringCbPrintf(szBuffer, sizeof(szBuffer), _T("jsInvokeCPlusPlus(%s,%s)"), strParam1.c_str(), strParam2.c_str());
            ::MessageBox(GetForegroundWindow(), szBuffer, _T("jsInvokeCPlusPlus"), MB_OK);
            retval = CefV8Value::CreateInt(0);
        }
        else
        {
            retval = CefV8Value::CreateInt(2);
        }

        return true;

    }

    if (name == L"jsTransform") {
        CefString strParam1 = arguments.at(0)->GetStringValue();
        TCHAR szBuffer[512];
        StringCbPrintf(szBuffer, sizeof(szBuffer), _T("jsTransform(%s)"), strParam1.c_str());
        ::MessageBox(GetForegroundWindow(), szBuffer, _T("jsTransform"), MB_OK);

    }

    // Function does not exist.
    return false;
}

HTML里面要怎么调用呢?

<html>
<script>
app.jsInvokeCPlusPlus("123","xyz");
app.jsTransform("hello world");
</script>
</html>

其中可能遇到的问题:
初始化Cef的时候必须把CCefClientApp作为参数传进去,这样才会响应OnWebKitInitialized回调。
如果是多进程模式的话,渲染子进程启动,执行CefExecuteProcess也必须传入CCefClientApp。

CefExecuteProcess(main_args, app, NULL);

相关文章

网友评论

      本文标题:CEF之c++与JS交互

      本文链接:https://www.haomeiwen.com/subject/dtwtiftx.html