如何实现CEF3JS与C语言的高效交互?

Cef3中js与c++交互主要通过V8引擎实现,包括窗口绑定和扩展两种方法。

CEF3中JavaScript与C交互详解

在现代Web开发中,Chromium Embedded Framework(CEF)是一个强大的工具,它允许开发者将Chromium浏览器嵌入到他们的桌面应用程序中,CEF3作为其最新版本,提供了更加丰富的功能和更高的性能,本文将详细探讨如何在CEF3中实现JavaScript与C++的交互,包括基本概念、具体步骤以及示例代码。

JavaScript与C++交互的基本概念

JavaScript与C++的交互通常涉及两个主要方面:从C++调用JavaScript(C++ to JS)和从JavaScript调用C++(JS to C++),这种双向通信机制使得开发者可以在桌面应用中充分利用Web技术的优势,同时保持对底层系统的控制。

1. 从C++调用JavaScript

从C++调用JavaScript通常用于执行前端脚本、修改DOM或响应用户事件,CEF3提供了CefFrame::ExecuteJavaScript()方法来执行JavaScript代码,该方法可以在渲染进程或浏览器进程中使用,并且可以在JS上下文之外执行。

2. 从JavaScript调用C++

从JavaScript调用C++则更为复杂,通常需要通过扩展JavaScript或绑定对象来实现,CEF3允许开发者注册自定义的JavaScript函数,这些函数可以调用本地的C++代码,从而实现JS to C++的通信。

从C++调用JavaScript

从C++调用JavaScript的过程相对简单,以下是一个基本的示例,展示如何使用CefFrame::ExecuteJavaScript()方法在C++中执行JavaScript代码。

示例:弹出消息框

#include "cef_browser.h"
#include "cef_frame.h"
// 假设已经有一个有效的browser对象
CefRefPtr<CefBrowser> browser;
// 获取主框架
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
// 执行JavaScript代码
frame->ExecuteJavaScript("alert('Hello from C++!');", frame->GetURL(), 0);

在这个示例中,我们首先获取了浏览器的主框架,然后使用ExecuteJavaScript()方法执行了一段简单的JavaScript代码,该代码将弹出一个消息框显示“Hello from C++!”。

从JavaScript调用C++

从JavaScript调用C++需要更多的设置步骤,下面是一个详细的示例,展示如何注册一个自定义的JavaScript函数,并在该函数中调用本地的C++代码。

步骤1:定义C++端接口

如何实现CEF3JS与C语言的高效交互?

我们需要在C++端定义一个接口,该接口将被JavaScript调用,这通常通过继承CefV8Handler类来实现。

#include "cef_v8handler.h"
class MyV8Handler : public CefV8Handler {
public:
    virtual bool Execute(const CefString& name,
                         CefRefPtr<CefV8Value> object,
                         const CefV8ValueList& arguments,
                         CefRefPtr<CefV8Value>& retval,
                         CefString& exception) OVERRIDE {
        if (name == "ShowMessage") {
            if (arguments.size() >= 1 && arguments[0].IsString()) {
                std::string message = arguments[0].GetStringValue();
                MessageBox(NULL, message.c_str(), "C++ Message", MB_OK);
                retval = CefV8Value::CreateString("Message shown");
                return true;
            }
        }
        return false;
    }
};

在这个示例中,我们定义了一个名为MyV8Handler的类,该类继承自CefV8Handler并重写了Execute方法,当JavaScript调用名为ShowMessage的函数时,这个方法将被触发。

步骤2:注册JavaScript扩展

我们需要在渲染进程中注册这个JavaScript扩展,以便JavaScript能够访问我们定义的函数。

void RegisterExtensions(CefRefPtr<CefBrowser> renderer) {
    std::string extensionCode = R"(
        var ShowMessage = function(message) {
            native function ShowMessage(message);
            return ShowMessage(message);
        };
    )";
    CefRefPtr<CefV8Context> context = renderer->GetMainFrame()->GetV8Context();
    context->RegisterExtension("v8/ShowMessage", extensionCode, new MyV8Handler());
}

在这个示例中,我们创建了一个名为RegisterExtensions的函数,该函数接收一个CefBrowser对象作为参数,我们使用RegisterExtension方法注册了一个名为v8/ShowMessage的扩展,并将我们之前定义的JavaScript代码和C++处理器关联起来。

步骤3:在JavaScript中调用C++函数

在HTML或JavaScript文件中调用我们注册的自定义函数。

<!DOCTYPE html>
<html>
<head>
    <title>My CEF App</title>
    <script type="text/javascript">
        function callNativeFunction() {
            console.log("Calling native function...");
            ShowMessage("Hello from JavaScript!");
        }
    </script>
</head>
<body>
    <button onclick="callNativeFunction()">Call Native Function</button>
</body>
</html>

在这个示例中,我们在HTML文件中添加了一个按钮,当点击该按钮时,将调用callNativeFunction函数,该函数进而调用我们注册的自定义JavaScript函数ShowMessage,从而触发C++端的Execute方法。

完整示例代码

以下是一个完整的示例代码,展示了如何在CEF3中实现JavaScript与C++的双向交互。

#include <windows.h>
#include "cef_app.h"
#include "cef_client.h"
#include "cef_browser.h"
#include "cef_frame.h"
#include "cef_v8handler.h"
#include "cef_render_process_handler.h"
#include "include/wrapper/cef_helpers.h"
class MyV8Handler : public CefV8Handler {
public:
    virtual bool Execute(const CefString& name,
                         CefRefPtr<CefV8Value> object,
                         const CefV8ValueList& arguments,
                         CefRefPtr<CefV8Value>& retval,
                         CefString& exception) OVERRIDE {
        if (name == "ShowMessage") {
            if (arguments.size() >= 1 && arguments[0].IsString()) {
                std::string message = arguments[0].GetStringValue();
                MessageBox(NULL, message.c_str(), "C++ Message", MB_OK);
                retval = CefV8Value::CreateString("Message shown");
                return true;
            }
        }
        return false;
    }
};
class SimpleHandler : public CefClient, public CefDisplayHandler, public CefLifeSpanHandler, public CefLoadHandler, public CefRenderProcessHandler {
public:
    SimpleHandler() : is_closing_(false) {}
    ~SimpleHandler() override {}
    // CefClient methods
    CefRefPtr<CefDisplayHandler> GetDisplayHandler() override { return this; }
    CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
    CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
    CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return this; }
    void OnRenderThreadCreated(CefRefPtr<CefListValue> params) override {}
    void OnWebKitInitialized() override { RegisterExtensions(browser_); }
    void OnBeforeBrowse(CefRefPtr<CefBrowser> browser) override {}
    void OnLoadEnd(CefRefPtr<CefBrowser> browser, bool frameOnly, int httpStatusCode) override {}
    void OnBeforeUnloadDialog(CefRefPtr<CefBrowser> browser, const CefString& reason, bool isReload) override {}
    void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {}
    void OnClose(CefRefPtr<CefBrowser> browser) override { is_closing_ = true; }
    void RunFileDialog(int mode, const std::wstring& title, const std::wstring& default_file, const std::wstring& accept_filter, int selected_accept_filter, const std::vector<std::wstring>& file_paths) override {}
    void OnBeforePopup(CefRefPtr<CefBrowser> parent_browser, CefRefPtr<CefFrame> frame, const CefString& target_url, CefRefPtr<CefBrowserSettings> browser_settings) override {}
    bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser, const CefString& url) override { return false; }
    void OnCertificateError(CefRefPtr<CefBrowser> browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr<CefSSLInfo> ssl_info, CefRefPtr<CefRequest> callback) override {}
    void OnPluginCrashed() override {}
    void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser, termination_status_t status) override {}
    void OnRendererUnresponsive(CefRefPtr<CefBrowser> browser) override {}
    bool OnProtocolExecution(const CefString& name, CefRefPtr<CefV8Context> context) override { return false; }
    void OnQuotaRequest(const CefString& origin_url, int64 new_size, const CefString& quota_table, void* callback_data) override {}
    void OnBrowserCreated(CefRefPtr<CefBrowser> browser) override { browser_ = browser; }
    void OnBrowserDestroyed() override {}
    void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) override { RegisterExtensions(browser); }
    void OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) override {}
    void OnBeforeDownload(const CefString& url, const CefString& suggested_name, const CefString& content_disposition, const CefString& mime_type, const CefString& download_dir, int download_id) override {}
    void OnDownloadUpdated(int download_id, CefRefPtr<CefDownloadItem> download_item, const CefString& download_item_download_id) override {}
    void OnExternalProtocolExecuted(const CefString& url) override {}
    void OnPostNavigationCommitPending(const CefRefPtr<CefNavigationEntry>& entry, bool is_main_frame) override {}
    void OnPostResourceResponseStart(const CefRefPtr<CefResponse>& response, bool frame_end) override {}
    void OnPreResourceLoad(const CefString& url) override {}
    bool IsWindowless() const override { return false; }
    void OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) override {}
    bool OnTooltip(CefRefPtr<CefBrowser> browser, const CefString& text) override {}
    void OnAddressChange(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& url) override {}
    bool OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, const CefString& method, const CefString& url, bool is_redirect) override {}
    CefReturnValue OnBeforeUnhandledKeyboardEvent(const MSG& msg, bool handled) override { return handled ? 1 : 0; }
    void OnBeforeFocus(bool set_focus) override {}
    bool OnDragEnter(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDragData> drag_data, CefMouseEvent event, int allowed_ops) override { return false; }
    void OnDraggableRegionsChanged(const std::vector<mojom::DraggableRegionPtr>& regions) override {}
    void OnBeforeDrop(CefRefPtr<CefBrowser> browser, CefRefPtr<CefDragData> drag_data, CefMouseEvent event, int allowed_ops) override {}
    void OnFileDialogAborted(int file_dialog_id) override {}
    void OnFindResult(int identifier, int count, const CefRange& selection_range, int active_match_ordinal, bool final_update) override {}
    void OnGetAuthPassword(const CefString& origin_url, const CefString& dialog_title, const CefString& username, const CefString& password) override {}
    void OnJumpToAnchor(const CefString& anchor_name) override {}
    bool ShouldCloseBrowser(bool force_close) override { return !is_closing_ && force_close; }
    bool ShouldHeuristicallyOpenPDF(const CefString& url) override { return false; }
    void OnMediaPlaybackStateChanged(const CefString& url, double currentTime, double duration) override {}
    void OnMediaMenuButtonEmitted(const std::wstring& path, int renderer_id) override {}
    void OnMediaRouteCreated(const std::wstring& media_route_id) override {}
    void OnMediaRouteClosed(const std::wstring& media_route_id) override {}
    bool OnTakeFocus(bool next, bool reverse) override {}
    bool OnSetFocus(bool source_null, CefFocusSource source) override { return false; }
    bool OnGotFocus(bool source_null, CefFocusSource source) override { return false; }
    bool OnLostFocus(bool source_null, CefFocusSource source) override { return false; }
private:
    CefRefPtr<CefBrowser> browser_;
    bool is_closing_;
};

原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1380658.html

本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。

(0)
未希新媒体运营
上一篇 2024-12-05 13:10
下一篇 2024-12-05 13:11

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

产品购买 QQ咨询 微信咨询 SEO优化
分享本页
返回顶部
云产品限时秒杀。精选云产品高防服务器,20M大带宽限量抢购 >>点击进入