1. 程式人生 > >libCEF中C++與JavaScript的互動呼叫

libCEF中C++與JavaScript的互動呼叫

前言

前一篇文章介紹過CEF在WIN32程式中嵌入chrome核心瀏覽器的例子:http://blog.csdn.net/mfcing/article/details/43973377

這裡介紹的是嵌入瀏覽器後,網頁的JS指令碼函式與C++程式碼的互動,這個很多地方都用得到。比如:音樂播放器裡網頁上的播放,客戶端資源中心裡的資源下載……

JS呼叫C++函式

首先需要重寫CefRenderProcessHandler的OnContextCreated介面,為什麼呢?學習CEF庫的使用必須仔細閱讀他的標頭檔案裡的注視部分:

  // Called immediately after the V8 context for a frame has been created. To
  // retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal()
  // method. V8 handles can only be accessed from the thread on which they are
  // created. A task runner for posting tasks on the associated thread can be
  // retrieved via the CefV8Context::GetTaskRunner() method.
  ///
  /*--cef()--*/
  virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefFrame> frame,
                                CefRefPtr<CefV8Context> context) {}
這個介面實在chrome的V8引擎建立後呼叫的,在這裡我們需要將JS裡面呼叫的函式和C++的執行函式關聯起來,這樣JS就可以“執行”C++程式碼了。

我們的函式都是定義在window物件中的(不知道JS中這個是不是叫物件),根據注視我們需要GetGlobal獲取這個物件。

我的程式碼是這樣的:

CefRefPtr<CefV8Value> window = context->GetGlobal();
		CefRefPtr<CefV8Accessor> myV8Acc = new CCefV8Accessor;
		CefRefPtr<CefV8Value> val = CefV8Value::CreateString(L"Application");
		CefString cefException;
		myV8Acc->Set(L"name", window, val, cefException);
		CefRefPtr<CefV8Value> pObjApp = CefV8Value::CreateObject(myV8Acc);
		window->SetValue(L"Application", pObjApp, V8_PROPERTY_ATTRIBUTE_NONE);

		CefRefPtr<CefV8Handler> myV8handle = new CCefV8Handler();
		CefRefPtr<CefV8Value> myFun = CefV8Value::CreateFunction(L"SetAppState", myV8handle);
		static_cast<CCefV8Handler*>(myV8handle.get())->AddFun(L"SetAppState", &CChromeJsCallback::JsSetAppState);
		pObjApp->SetValue(L"SetAppState", myFun, V8_PROPERTY_ATTRIBUTE_NONE);

		myFun = CefV8Value::CreateFunction(L"OneClickInstall", myV8handle);
		static_cast<CCefV8Handler*>(myV8handle.get())->AddFun(L"OneClickInstall", &CChromeJsCallback::JsOneKeyInstall);
		pObjApp->SetValue(L"OneClickInstall", myFun, V8_PROPERTY_ATTRIBUTE_NONE);

		myFun = CefV8Value::CreateFunction(L"DownLoadFile", myV8handle);
		static_cast<CCefV8Handler*>(myV8handle.get())->AddFun(L"DownLoadFile", &CChromeJsCallback::JsDownloadFile);
		pObjApp->SetValue(L"DownLoadFile", myFun, V8_PROPERTY_ATTRIBUTE_NONE);

所有的JS函式都是在window.Application上的,因此需要在window 物件上面建立Application 物件,CefV8Value::CreateObject用來建立物件。CefV8Value這個類在JS處理中至關重要,要必要好好看看標頭檔案裡面的注視,CEF的注視是相當詳細的。

建立函式物件,並將JS函式繫結到C++函式指標上面的過程是重點詳細介紹下

CefRefPtr<CefV8Handler> myV8handle = new CCefV8Handler();
		CefRefPtr<CefV8Value> myFun = CefV8Value::CreateFunction(L"SetAppState", myV8handle);
		static_cast<CCefV8Handler*>(myV8handle.get())->AddFun(L"SetAppState", &CChromeJsCallback::JsSetAppState);
		pObjApp->SetValue(L"SetAppState", myFun, V8_PROPERTY_ATTRIBUTE_NONE);



AddFun是自己新增的一個函式,用來把一個函式和氣對應的回撥地址儲存到這個V8物件中,因此用了一個成員變數typedef map<CefString, JS_CALLBACK_FUN> FunctionMap,呼叫函式時V8引擎有一個介面Execute,在這裡我們呼叫函式的名稱到map中去查詢,找到了其對應的回撥地址呼叫函式,這就是JS呼叫C++的過程了。

最上面那段程式碼中,我們又添加了三個函式 SetAppState、OneClickInstall、DownLoadFile到window.application物件上面。

C++程式碼中,這三個函式是這樣寫的:

//JS函式,在其他程序中呼叫
	static bool	JsSetAppState(const CefV8ValueList& argList, CefRefPtr<CefV8Value>& retValue);
	static bool	JsOneKeyInstall(const CefV8ValueList& argList, CefRefPtr<CefV8Value>& retValue);
	static bool	JsDownloadFile(const CefV8ValueList& argList, CefRefPtr<CefV8Value>& retValue);

vCefV8ValueList是一個引數列表,看它的定義typedef std::vector<CefRefPtr<CefV8Value> > CefV8ValueList,retValue當然就是函式的返回值了,有的JS需要根據返回值做相應的處理的。

這裡要注意:CEF可以使用單程序和多程序模式,我程式裡使用的是多程序模式,因此V8引擎的執行是在渲染引擎裡的,不要嘗試在這裡直接去對介面進行處理。介面程序和渲染程序是分開的,資料的話用共享記憶體來做,介面更新發訊息來做。

C++呼叫JS函式

C++呼叫JS函式相對簡單多了,因為CEF有介面可以直接使用CefFrame::ExecuteJavaScript,看看註釋:

  // Execute a string of JavaScript code in this frame. The |script_url|
  // parameter is the URL where the script in question can be found, if any.
  // The renderer may request this URL to show the developer the source of the
  // error.  The |start_line| parameter is the base line number to use for error
  // reporting.
  ///
  /*--cef(optional_param=script_url)--*/
  virtual void ExecuteJavaScript(const CefString& code,
                                 const CefString& script_url,
                                 int start_line) =0;

首先需要獲取到我們的瀏覽器裡的主框架物件,code是JS函式和傳入引數的字串,URL可以直接忽略。
void CChromeBrowserUI::ExecuteJavascript( const wstring& strCode )
{
	if ( m_pWebBrowser.get() )
	{
		CefRefPtr<CefFrame> frame = m_pWebBrowser->GetMainFrame();
		if ( frame.get() )
		{
			CefString strCode(strCode.c_str()), strUrl(L"");
			frame->ExecuteJavaScript(strCode, strUrl, 0);
		}
	}
}
注意:函式名和引數名需要用單引號分隔。

我的字串格式化部分:

CString strJsCode;
	strJsCode.Format(L"setInstallStatus('%s','%s','%d');", lpData->strId.c_str(), strStatus, nPercent);

這樣,C++就可以呼叫JS的函式並傳入對應的引數了。

總結

要想使用CEF,最好還是仔細閱讀標頭檔案裡面的註釋,很詳細。 執行程式

相關推薦

libCEFC++JavaScript互動呼叫

前言 前一篇文章介紹過CEF在WIN32程式中嵌入chrome核心瀏覽器的例子:http://blog.csdn.net/mfcing/article/details/43973377 這裡介紹的是嵌入瀏覽器後,網頁的JS指令碼函式與C++程式碼的互動,這個很多地方都用得到

在 Cef 實現 C++ JavaScript 互動場景分析

此文已由作者鄧佳佳授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗 本文主要介紹 CEF 場景中 C++ 和 JavaScript 互動(以下簡稱 JS Bridge)中的一些重要節點,包括了 C++/JavaScript 的方法註冊、方法呼叫、回撥管理。以下是一些

FlexJavaScript互動呼叫函式

一、在JavaScript中呼叫Flex方法  在 Flex 應用中,需要在方法列表中新增指定的公用方法,這樣Flex中的方法才能被JS呼叫到。在Flex中需要通過呼叫addCallback()可以把一個方 法新增到此列表中。 addCallback將一個ActionScr

androidWebviewjavascript互動(互相呼叫

最近做android專案中遇到要在webview中做與js互動相關的東東,涉及到js中呼叫android本地的方法,於是查了資料整理了一下android和js互相呼叫的過程。如下demo,demo的主要實現過程如下:通過載入本地的html檔案(裡面有js指令碼),實現and

iOS 開發 Object-CJavaScript互動詳解之OCJS互動在WKWebView使用

1.OC與JS互動在UIWebView中使用 2. WKWebView的使用詳解 3.OC與JS互動在WKWebView中使用 // // ViewController.m // oc與js互動WKWebView // // Cr

VCJavaScript互動(三) ———— JS呼叫C++

太監的原因:     時隔兩年,VC與JavaScript互動系列的最後一篇關於JavaScript如何呼叫c++的文章終於出爐了。為什麼會隔了那麼久?因為本來打算太監的,可是看到熱情的網友們的眼神,從期望變成了失望,在我的心裡激起了層層波瀾。兩年後的今天,還是堅持

FlexJavaScript互動如何用Flex呼叫JavaScript

本文和大家重點討論一下Flex與JavaScript的互動:Flex呼叫JavaScript或者被JavaScript呼叫,在Flex中呼叫JavaScript最簡單的方法是使用ExternalInterface(),可以使用此API呼叫任意JavaScript,傳遞引數,獲

C++QML互動2:在QML呼叫C++特性

版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。 本文連結:https:/

C++Lua互動1: C++呼叫lua

lua作為一門動態語言,可用來當做配置檔案和實現經常變化的業務功能,很方便的實現熱更新。同時lua作為一門膠水語言,配合強大的C++作邏輯支撐,程式效能高、開發效率快,猶如珠簾合璧,所向無敵。C++與lua的互動主要通過lua的虛擬棧實現,本文不打算深入講解其

C#webbrowserjavascript(js)交互的方法

新建 基本 tool 開發環境 應用 pub click show 還需要 今天在做一個項目的時候需要用c#搞一個webbrowser,然後有些地方還需要與js交互。所以就查了一下資料,發現很多博客提到了但是卻沒有說下具體的操作。所以我就寫一下. 開發環境是Visual

VCJavaScript互動(四) ———— WebBrowser或CHtmlView輕鬆遮蔽指令碼錯誤(JavaScript)

1.什麼是javascript指令碼錯誤 1.1    概述 JavaScript指令碼錯誤包含“執行時錯誤”和“語法錯誤”。 1.2    JavaScript“語法錯誤” JavaScript語法錯誤是指當 JavaScript語句違反了 JavaScript指令碼語言

C#通過webbrowser控制元件javascript互動

1.C#裡呼叫控制元件裡面網頁的js函式     //呼叫JavaScript的messageBox方法,並傳入引數     object[] objects = new object[1];     objects[0] = “C#訪問JavaScript指令碼";  

VCJavaScript互動(二) ———— 呼叫JS函式

這一章,我們來動手實踐VC呼叫JS函式。 我們動手寫一個HTML,其中包含這樣一段JS程式碼: <script type="text/javascript"> function Add(value1, value2) { return

Android:WebViewJavascript互動(相互呼叫引數、傳值)

Android中可以使用WebView載入網頁,同時Android端的java程式碼可以與網頁上的javascript程式碼之間相互呼叫。 效果圖: (一)Android部分: 佈局程式碼: <LinearLayout xmlns:android="http://s

在 Mac Webview Objective-c JS 互動

http://blog.eqoe.cn/posts/mac-webview-js-oc.html 本文為您圖文演示如何在 OC 中註冊或執行 JS 函式,以實現網頁與程式的互動。 1. 首先我們建立一個 XCode 專案; 2. 新增WebView 到ViewContro

unity c# object-c 互動

C/C++可以直接與object-c互動,只需把檔案字尾寫成.mm就行了。c#又可以和C/C++互動,所以嘛。。。c#也就可以和object-c互動了。 1、在unity中 c#呼叫object-c 函式 首先,定義一個新建一個.mm檔案,然後在裡面定義一個C風格介面的函

c/c++_stdcalldll動態呼叫

1._stdcall在動態dll呼叫中的注意事項 為了用vc寫的dll能被其它語言的寫的程式使用,即實現跨語言。我們在dll的函式呼叫約定中使用__stdcall . 但當用GetProcAddress呼叫是卻失敗了. 用dumpbin工具檢視匯出的函式名可以看到

MFC的WebBrowser控制元件 C++JavaScript之間資料互動傳遞

----------------------------------------------------------------------------------------------------------------------------------------

unityc#Objective-C相互呼叫

前言 在unity中接入sdk或者定製一些功能時,需要呼叫系統介面。iphone手機實際操作中,也就是Unity與iOS相互呼叫。我們在Unity中使用c#,iOS中使用Objective-C(以下稱為oc)。 下面介紹他們如何相互呼叫。 c# 呼叫

WebViewJavaJavaScript互動

> 原文首發於微信公眾號:jzman-blog,歡迎關注交流! Android 開發過程中 WebView 的使用比較廣泛,常用來載入網頁,比如使用 WebView 載入新聞頁面、使用 WebView 開啟本應用的連結以及用 WebView 顯示支付資訊頁面等,那麼如何 Android 開發中如何與