Cef3中js与C++交互(三)——JS扩展

注册新的V8扩展关联指定的js

扩展像window绑定一样除了为每个框架 加载到上下文之外,一旦加载就不能修改,当一个扩展已经加载并试图在扩展加载中访问DOM就会出现DOM不存在的crash。扩展应该在CefRenderProcessHandler::OnWebKitInitialized()函数中使用CefRegisterExtension函数注册。
看看官方的例子:

void MyRenderProcessHandler::OnWebKitInitialized() {
  // Define the extension contents.
  std::string extensionCode =
    "var test;"
    "if (!test)"
    "  test = {};"
    "(function() {"
    "  test.myfunc = function() {"
    "    native function myfunc();"
    "    return myfunc();"
    "  };"
    "})();";

  // Create an instance of my CefV8Handler object.
  CefRefPtr<CefV8Handler> handler = new MyV8Handler();

  // Register the extension.
  CefRegisterExtension("v8/test", extensionCode, handler);
}
<script language="JavaScript">
alert(test.myfunc()); // Shows an alert box with "My Value!"
</script>

我们再用自己的例子来验证一下。

可以在上一篇的例子代码中修改。

V8JsHandler.cpp

#include "V8JsHandler.h"

CV8JsHandler::CV8JsHandler(void)
{
}

CV8JsHandler::~CV8JsHandler(void)
{
}

bool CV8JsHandler::Execute(const CefString& funcName,
							 CefRefPtr<CefV8Value> object,
							 const CefV8ValueList& arguments,
							 CefRefPtr<CefV8Value>& retval,
							 CefString& exception)
{
    //function add
    if (funcName == "add")
    {
        int32  val2 = arguments[0]->GetIntValue();
        int32  val1 = arguments[1]->GetIntValue();
        int32 sum = val1 + val2;
        retval = CefV8Value::CreateInt(sum);
        return true;
    }
    return false;
}

simple_app.h

#pragma once

#include "include/cef_app.h"

class SimpleApp
    : public CefApp
    , public CefBrowserProcessHandler
    , public CefRenderProcessHandler
{
public:
    SimpleApp(void);
    virtual ~SimpleApp() OVERRIDE;

public:
    virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE;
    virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE;
    virtual void OnWebKitInitialized() OVERRIDE;

protected:
    IMPLEMENT_REFCOUNTING(SimpleApp);
};

simple_app.cc

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "simple_app.h"

#include <string>

#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
#include "include/wrapper/cef_helpers.h"
#include "simple_handler.h"

#include "V8JsHandler.h"

SimpleApp::SimpleApp() {}

SimpleApp::~SimpleApp()
{

}

CefRefPtr<CefBrowserProcessHandler> SimpleApp::GetBrowserProcessHandler()
{
    return this;
}

CefRefPtr<CefRenderProcessHandler> SimpleApp::GetRenderProcessHandler()
{
    return this;
}

void SimpleApp::OnWebKitInitialized()
{
     CEF_REQUIRE_RENDERER_THREAD()

    // Define the extension contents.
//    std::string extensionCode =
//            "var MyMath;"
//            "if (!MyMath)"
//            "  MyMath = {};"
//            "(function() {"
//            "  MyMath.add = function(num1, num2) {"
//            "    native function add();"
//            "    return add(num1, num2);"
//            "  };"
//            "  MyMath.hellow = 'Hello JS!';"
//            "})();";

    std::string extensionCode = R"(
        var MyMath;
        if (!MyMath)
            MyMath = {};

        (function() {
            MyMath.add = function(num1, num2) {
                native function add();
                return add(num1, num2);
            };
            MyMath.hellow = 'Hello JS!';
        })();
    )";

     //以上两种方式都可以 R"()"是c++11中新增的多行字符串写法
     //native function add(); 这个不能少,可以写成native function add(int, int);
     //注意多行字符串中不能出现注释,否则会有问题,比如调用的时候发现undefined问题,或者出现少了;的错误提示

    CefRefPtr<CefV8Handler> addHandler = new CV8JsHandler();
    // Register the extension.
    CefRegisterExtension("v8/test", extensionCode, addHandler); //第一个参数不能为空,否则报错,这个名字可以自定义
}

index.html

<!DOCTYPE HTML>
<html>
	<head>
		<meta charset="utf-8" />
		<script type="text/javascript" >
			function CallMyMathAdd()
			{
				try{
					var result = MyMath.add(10, 20);// C++提供的接口,bind到window对象上
					alert("10 + 20 = " + result);
				}catch(err){
					alert("error message: " + err.message);
				}
			}
			function CallMyMathVar()
			{
				try{
					alert("MyMath.hellow: " + MyMath.hellow);
				}catch(err){
					alert("error message: " + err.message);
				}
			}
		</script>
	</head>
	<body style="width:100%;height:100%;background-color:green;">
		<p>这是c++与JS交互测试脚本</p>
		<div >
			<button onclick="CallMyMathAdd();">两个数相加</button>
			<button onclick="CallMyMathVar();">MyMath的值</button>
		</div>
	</body>
</html>

运行结果:
在这里插入图片描述

在这里插入图片描述

如果少了

native function add();

就会出现异常:
在这里插入图片描述
异常的字符串是add is not defined

注意extensionCode的两种写法都可以,R"()"是C++11中新增的多行字符串的写法,要注意的是C++中的js代码中的注释也可能出问题,删掉这些注释就好了。

链接:https://pan.baidu.com/s/1mvYLiLII9j9WKHzriNGDNg
提取码:veky


版权声明:本文为hp_cpp原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。