在CEF3(Chromium Embedded Framework)中,JavaScript与C++的交互是一个复杂但功能强大的特性,通过这种交互,开发者可以在客户端应用程序中充分利用JavaScript的灵活性和C++的性能优势,以下是关于CEF3中JS与C++交互的详细解析:
一、基本概念
1、V8引擎:
CEF3使用V8 JavaScript引擎来执行内部的JavaScript代码,每一个Frame在浏览器进程中都有一个属于自己的JS上下文,该上下文提供了一个安全和有限的环境来执行JS代码。
2、渲染进程:
Chromium和CEF使用V8引擎运行在独立的渲染进程中,渲染进程中的主线程命名为TID_RENDERER,所有的V8运行在这个线程中。
3、回调机制:
JS APIs被设计成通过异步回调方法在浏览器和渲染进程之间通讯。
二、执行JavaScript
在客户端执行JavaScript最简单的方法是使用CefFrame::ExecuteJavaScript()
函数,该函数在浏览器和渲染进程中都可以使用,并且能在JS上下文之外使用。
CefRefPtr<CefBrowser> browser = ...; CefRefPtr<CefFrame> frame = browser->GetMainFrame(); frame->ExecuteJavaScript("alert('ExecuteJavaScript works!');", frame->GetURL(), 0);
上述代码将在browser的主Frame中弹出一个对话框,显示“ExecuteJavaScript works!”。
三、窗口绑定
窗口绑定允许客户端应用程序将值附加到一个框架窗口对象上,窗口绑定使用CefRenderProcessHandler::OnContextCreated()
方法实现。
void MyRenderProcessHandler::OnContextCreated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) { // Retrieve the context's window object. CefRefPtr<CefV8Value> object = context->GetGlobal(); // Create a new V8 string value. CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!"); // Add the string to the window object as "window.myval". object->SetValue("myval", str, V8_PROPERTY_ATTRIBUTE_NONE); }
JavaScript代码可以与窗口绑定相配合使用:
<script language="JavaScript"> alert(window.myval); // Shows an alert box with "My Value!" </script>
四、扩展
扩展和窗口绑定类似,除了在每个框架的上下文中加载和加载后不能修改,当扩展加载后DOM不存在和在扩展加载期间试图访问DOM将会导致崩溃,扩展使用CefRegisterExtension()
函数注册,在CefRenderProcessHandler::OnWebKitInitialized()
方法中调用。
void MyRenderProcessHandler::OnWebKitInitialized() { // Define the extension contents. std::string extensionCode = "var test;" "if (!test)" " test = {};" "(function() {" " test.myval = 'My Value!';" "})();"; // Register the extension. CefRegisterExtension("v8/test", extensionCode, NULL); }
JavaScript代码可以与扩展相配合使用:
<script language="JavaScript"> alert(test.myval); // Shows an alert box with "My Value!" </script>
五、基本的JS类型
CEF支持创建JS基本数据类型,包括undefined, null, bool, int, double, date和string,这些类型使用CefV8Value::Create*()
静态方法创建,创建一个新的JS string类型使用CreateString()
方法。
CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!");
六、JS简单回调
本地代码可以通过ExecuteFunction()
和ExecuteFunctionWithContext()
执行JS函数。
void MyRenderProcessHandler::OnContextCreated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) { // Retrieve the context's window object. CefRefPtr<CefV8Value> object = context->GetGlobal(); CefRefPtr<CefV8Handler> handler = new MyV8Handler(this); object->SetValue("register", CefV8Value::CreateFunction("register", handler), V8_PROPERTY_ATTRIBUTE_NONE); }
在MyV8Handler::Execute()
的实现中对"register"的context和function保存引用。
bool MyV8Handler::Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) { if (name == "register") { if (arguments.size() == 1 && arguments[0]->IsFunction()) { callback_func_ = arguments[0]; callback_context_ = CefV8Context::GetCurrentContext(); return true; } } return false; }
通过JavaScript注册JS callback。
function myFunc() { // do something in JS. } window.register(myFunc);
在随后的某个时候执行JS callback。
CefV8ValueList args; CefRefPtr<CefV8Value> retval; CefString exception; if (callback_func_->ExecuteFunctionWithContext(callback_context_, NULL, args, retval, exception, false)) { if (exception.get()) { // Execution threw an exception. } else { // Execution succeeded. } }
七、JS异步回调
JavaScript与C++之间可以实现异步通信,但不能跨进程通信,当JavaScript与renderer进行实现异步通信时,可以参考sayHello实现,以下是一个使用JavaScript读取本地文本文件的案例来探索如何在CEF中实现JavaScript与C++之间的跨进程异步调用。
八、FAQs
1、Q: CEF3中的JS与C++如何进行交互?
A: CEF3中的JS与C++交互主要通过V8 JavaScript引擎实现,可以使用CefFrame::ExecuteJavaScript()
函数执行JavaScript代码,或者通过窗口绑定和扩展将值附加到框架窗口对象上,还可以使用ExecuteFunction()
和ExecuteFunctionWithContext()
方法执行JS函数,并通过回调机制实现异步通信。
2、Q: CEF3中如何创建和使用JS基本数据类型?
A: CEF3支持创建JS基本数据类型,包括undefined, null, bool, int, double, date和string,这些类型使用CefV8Value::Create*()
静态方法创建,创建一个新的JS string类型使用CreateString()
方法。
到此,以上就是小编对于“cef3 c js”的问题就介绍到这了,希望介绍的几点解答对大家有用,有任何问题和不懂的,欢迎各位朋友在评论区讨论,给我留言。
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1378553.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复