【CEF】 VC应用程序让JS代码能够调用C++方法

介绍

Chromium和CEF使用V8 JavaScript引擎 作为它们内部的Javascript实现。浏览器中的每一页(Frame)都有它自己的JS上下文,上下文提供一个空间和安全机制来执行页面上的JS代码,CEF为客户应用程序暴露了多个JS特性,其中js扩展可实现js代码调用c++方法

实现:

1、注册一个V8扩展与js代码

void InitExtensionTest() {
  // Register a V8 extension with the below JavaScript code that calls native
  // methods implemented in ClientV8ExtensionHandler.
  std::string code = "var cef;"
    "if (!cef)"
    "  cef = {};"
    "if (!cef.test)"
    "  cef.test = {};"
    "(function() {"
    "  cef.test.__defineGetter__('test_param', function() {"
    "    native function GetTestParam();"
    "    return GetTestParam();"
    "  });"
    "  cef.test.__defineSetter__('test_param', function(b) {"
    "    native function SetTestParam();"
    "    if (b) SetTestParam(b);"
    "  });"
    "  cef.test.test_object = function() {"
    "    native function GetTestObject();"
    "    return GetTestObject();"
    "  };"
	"  cef.test.loadurl = function(val) {"
	"    native function loadurl();"
	"    return loadurl(val);"
	"  };"
	" cef.test.IndicatorsCloud = function(val1, val2) {"
	"    native function IndicatorsCloud();"
	"    return IndicatorsCloud(val1, val2);"
	"  };"
    "})();";
  CefRegisterExtension("v8/test", code, new ClientV8ExtensionHandler());//code表示的字符串是任意合法的JS代码
}

2、定一个类继承CefV8Handler,并实现Execute,用来判断js代码调用本地c++方法名称,并能够接收参数传递和返回值

class ClientV8ExtensionHandler : public CefV8Handler {
 public:
  ClientV8ExtensionHandler() : test_param_("An initial string value.") {}
  virtual ~ClientV8ExtensionHandler() {}

  // Execute with the specified argument list and return value.  Return true if
  // the method was handled.
  //该方法继承CefV8Handler必需实现
  //功能:判断js调用的本地方法名称,接收参数传递和返回值,实现方法具体功能
  virtual bool Execute(const CefString& name,
                       CefRefPtr<CefV8Value> object,
                       const CefV8ValueList& arguments,
                       CefRefPtr<CefV8Value>& retval,
                       CefString& exception) {
    if (name == "SetTestParam") {
      // Handle the SetTestParam native function by saving the string argument
      // into the local member.
      if (arguments.size() != 1 || !arguments[0]->IsString())
        return false;

      test_param_ = arguments[0]->GetStringValue();
      return true;
    } else if (name == "GetTestParam") {
      // Handle the GetTestParam native function by returning the local member
      // value.
      retval = CefV8Value::CreateString(test_param_);
      return true;
    } else if (name == "GetTestObject") {
      // Handle the GetTestObject native function by creating and returning a
      // new V8 object.
      retval = CefV8Value::CreateObject(NULL);
      // Add a string parameter to the new V8 object.
      retval->SetValue("param", CefV8Value::CreateString(
          "Retrieving a parameter on a native object succeeded."),
          V8_PROPERTY_ATTRIBUTE_NONE);
      // Add a function to the new V8 object.
      retval->SetValue("GetMessage",
          CefV8Value::CreateFunction("GetMessage", this),
          V8_PROPERTY_ATTRIBUTE_NONE);
      return true;
    }  else if (name == "GetMessage") {
      // Handle the GetMessage object function by returning a string.
      retval = CefV8Value::CreateString(
          "Calling a function on a native object succeeded.");
      return true;
    }
	else if (name == "loadurl")
	{
		if (arguments.size() != 1)
			return false;
		if (arguments[0]->IsString())
		{
			retval =  CefV8Value::CreateString( arguments[0]->GetStringValue());
		}
		return true;
	}
	else if (name == "IndicatorsCloud")
	{
		if (arguments.size() != 2)
			return false;
		if (arguments[0]->IsInt() && arguments[1]->IsString())
		{
			retval = CefV8Value::CreateInt(arguments[0]->GetIntValue());
		}
		return true;
	}
    return false;
  }

 private:
  CefString test_param_;

  IMPLEMENT_REFCOUNTING(ClientV8ExtensionHandler);
};

3、执行js代码测试调用c++方法

void RunExtensionTest(CefRefPtr<CefBrowser> browser) {
	std::string html =
		"<html><body>ClientV8ExtensionHandler says:<br><pre>"
		"<script language=\"JavaScript\">"
		"cef.test.test_param ="
		"  'Assign and retrieve a value succeeded the first time.';"
		"document.writeln(cef.test.test_param);"
		"cef.test.test_param ="
		"  'Assign and retrieve a value succeeded the second time.';"
		"document.writeln(cef.test.test_param);"
		"var obj = cef.test.test_object();"
		"document.writeln(obj.param);"
		"document.writeln(obj.GetMessage());"
		"document.writeln(cef.test.loadurl(\"hello world.\"));"
		"document.writeln(cef.test.IndicatorsCloud(123456789, \"leadsec.\"));"
    "</script>"
    "</pre></body></html>";
  browser->GetMainFrame()->LoadString(html, "about:blank");
}



你可能感兴趣的:(【CEF】 VC应用程序让JS代码能够调用C++方法)