How to Expose C++ Qt WebView and Window Functions to Python?

teejayredex

teejayRedex

Posted on November 21, 2024

How to Expose C++ Qt WebView and Window Functions to Python?

I'm working on a project where I need to integrate a Qt6 WebView into Python. The WebView should allow dynamic control from Python, including:

  • Setting the window size and style (e.g., resizing, full-screen,
    borderless).

  • Loading HTML content or a URL dynamically.

  • Interacting with JavaScript in the WebView.

What I Want to Achieve:

Dynamically set window properties (e.g., resize(800, 600), borderless mode, etc.).
Load either:

  • Raw HTML content (loadHtml).

  • A remote URL (loadUrl).

  • Execute and interact with JavaScript in the WebView (e.g., calling JS
    functions or retrieving results).

  • Expose all these functionalities to Python without relying on PySide
    or PyQt due to licensing concerns.

What I’ve Tried:

  • I’ve attempted to use pybind11 to expose a custom C++ class that wraps QApplication and QWebEngineView. Here's an example of my pybind11 bindings:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <QApplication>
#include <QWebEngineView>
#include <QString>

namespace py = pybind11;

class WebView {
public:
    WebView() {
        int argc = 0;
        char *argv[] = {nullptr};
        app = std::make_unique<QApplication>(argc, argv);
        view = std::make_unique<QWebEngineView>();
    }

    void resize(int width, int height) {
        view->resize(width, height);
    }

    void setHtml(const std::string &html) {
        view->setHtml(QString::fromStdString(html));
    }

    void setUrl(const std::string &url) {
        view->setUrl(QUrl(QString::fromStdString(url)));
    }

    void exec() {
        view->show();
        app->exec();
    }

private:
    std::unique_ptr<QApplication> app;
    std::unique_ptr<QWebEngineView> view;
};

PYBIND11_MODULE(qt_webview, m) {
    py::class_<WebView>(m, "WebView")
        .def(py::init<>())
        .def("resize", &WebView::resize)
        .def("setHtml", &WebView::setHtml)
        .def("setUrl", &WebView::setUrl)
        .def("exec", &WebView::exec);
}
Enter fullscreen mode Exit fullscreen mode
  • The code compiles fine, and I cannot load basic HTML and URLs in the WebView from Python due to ImportError: /home/red-x/Documents/GUIEngine/MyQtWebViewApp/qt_webview.cpython-312-x86_64-linux-gnu.so: undefined symbol: qt_version_ta. However:
  1. I cannot tweak window styles (e.g., borderless or full-screen).
    Ubuntu

  2. I can't execute or retrieve JavaScript results from Python.

  3. I feel my approach isn't complete or robust for all the features I
    need.

Constraints:

  • No PySide or PyQt: I need a solution without these libraries because
    of their licensing restrictions.

  • Why pybind11?: It fits my requirements for lightweight and
    license-compliant bindings.

Questions:

  • How can I expose Qt's window and WebView functionalities (e.g.,
    styles, JavaScript interaction) to Python using pybind11?

  • Is there a better way to handle this integration without relying on
    PySide or PyQt?

  • Are there examples or open-source projects that achieve something
    similar?

Environment:

OS:  Windows 10 or Ubuntu 20.04
Qt Version: 6.4.2
Python Version: 3.12
Compiler: g++ with C++17
Enter fullscreen mode Exit fullscreen mode

Any help or suggestions would be greatly appreciated!

💖 💪 🙅 🚩
teejayredex
teejayRedex

Posted on November 21, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related