首先定义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);
网友评论