JS对象可选择使用一个与之关联的CefV8Accessor以提供一个源生的getting和setting值的实现
套路:
CefRefPtr<CefV8Accessor> accessor = …;
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
接下来就是继承CefV8Accessor,重写Get和Set接口
class MyV8Accessor : public CefV8Accessor {
public:
MyV8Accessor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
if (name == "myval") {
// Return the value.
retval = CefV8Value::CreateString(myval_);
return true;
}
// Value does not exist.
return false;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
if (name == "myval") {
if (value->IsString()) {
// Store the value.
myval_ = value->GetStringValue();
} else {
// Throw an exception.
exception = "Invalid value type";
}
return true;
}
// Value does not exist.
return false;
}
// Variable used for storing the value.
CefString myval_;
// Provide the reference counting implementation for this class.
IMPLEMENT_REFCOUNTING(MyV8Accessor);
};
In order for a value to be passed to the accessor it must be set using
the SetValue() method variant that accepts AccessControl and
PropertyAttribute arguments.
翻译:
为了将值传递给accessor,必须设置SetValue()方法,并且需要设置AccessControl和PropertyAttribute 参数。
obj->SetValue("myval", V8_ACCESS_CONTROL_DEFAULT,
V8_PROPERTY_ATTRIBUTE_NONE);
官网的介绍就这么多,怎么用呢?
我用Qt写了个demo
MyV8Accessor.h
#ifndef MYV8ACCESSOR_H
#define MYV8ACCESSOR_H
#include "include/cef_v8.h"
class MyV8Accessor : public CefV8Accessor
{
public:
MyV8Accessor();
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE;
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE;
private:
// Variable used for storing the value.
CefString myval_ = "ha ha";
// Provide the reference counting implementation for this class.
IMPLEMENT_REFCOUNTING(MyV8Accessor);
};
#endif // MYV8ACCESSOR_H
MyV8Accessor.cpp
#include "MyV8Accessor.h"
#include <QMessageBox>
MyV8Accessor::MyV8Accessor()
{
}
bool MyV8Accessor::Get(const CefString &name, const CefRefPtr<CefV8Value> object, CefRefPtr<CefV8Value> &retval, CefString &exception)
{
if (name == "myval")
{
QMessageBox::information(nullptr, "title", "MyV8Accessor Get");
// Return the value.
retval = CefV8Value::CreateString(myval_);
return true;
}
// Value does not exist.
return false;
}
bool MyV8Accessor::Set(const CefString &name, const CefRefPtr<CefV8Value> object, const CefRefPtr<CefV8Value> value, CefString &exception)
{
if (name == "myval")
{
if (value->IsString())
{
QMessageBox::information(nullptr, "title", "MyV8Accessor Set");
// Store the value.
myval_ = value->GetStringValue();
} else {
// Throw an exception.
exception = "Invalid value type";
}
return true;
}
// Value does not exist.
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 OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,CefRefPtr<CefV8Context> context) 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 "MyV8Accessor.h"
SimpleApp::SimpleApp()
{
}
SimpleApp::~SimpleApp()
{
}
CefRefPtr<CefBrowserProcessHandler> SimpleApp::GetBrowserProcessHandler()
{
return this;
}
CefRefPtr<CefRenderProcessHandler> SimpleApp::GetRenderProcessHandler()
{
return this;
}
void SimpleApp::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
{
CEF_REQUIRE_RENDERER_THREAD()
CefRefPtr<CefV8Value> window = context->GetGlobal();
CefRefPtr<CefV8Accessor> accessor = new MyV8Accessor();
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor, nullptr);
obj->SetValue("myval", V8_ACCESS_CONTROL_DEFAULT, V8_PROPERTY_ATTRIBUTE_NONE);
window->SetValue("MyValObj", obj, V8_PROPERTY_ATTRIBUTE_NONE);
}
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" >
function getMethod()
{
try{
alert("MyValObj.myval: " + MyValObj.myval);
}catch(err){
alert("error message: " + err.message);
}
}
function setMethod()
{
try{
MyValObj.myval = "hello world"
}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="getMethod();">Get方法</button>
<button onclick="setMethod();">Set方法</button>
</div>
</body>
</html>
运行结果:
我让它弹了两个框,第一个是Qt的QMessageBox,判断MyV8Accessor的Get方法是否被调用,第二个是网页上的弹框,获取值。
惯例,全部的代码,如果跑不起来,则参考前面的环境配置和目录结构
链接:https://pan.baidu.com/s/1SsX4w92v2IzV4czEmH2low
提取码:w12c