CXX-Qt

repository·main·Indexed 23 days ago

https://github.com/kdab/cxx-qt

A framework for creating bidirectional Rust and C++ bindings for the Qt framework. CXX-Qt enables developers to implement QObjects in Rust and use them in C++ or QML applications, providing safe interop via the cxx crate. It includes code generators for Qt's signals, slots, and property system, and provides bindings to common QtCore and QtGui classes. Supports Qt 5.15 LTS and all versions of Qt 6.

Tokens
22.5K
Snippets
40
Records
146
Agent score
78%

What's inside cxx-qt

  1. Overview of CXX-Qt

    main

    CXX-Qt is a library designed to automate the generation of code for transferring data between Rust and C++. It enables the creation of common interfaces, such as QObjects, which can be exposed directly into QML.

    Key architectural details:

    • Internal Dependency: It relies on the cxx crate to facilitate the Rust/C++ boundary.
    • Extensibility: For Qt interactions not covered by the built-in code generators, it is recommended to implement the logic directly in C++ and connect it to Rust using cxx code.
    • Build System: The build system is based on CMake, but it remains compatible with standalone cxx workflows.
  2. What is CXX-Qt?

    main

    CXX-Qt is a set of Rust crates designed for creating bidirectional Rust ⇄ C++ bindings with Qt. It allows you to:

    • Integrate Rust into C++ applications using CMake.
    • Build Rust applications with Cargo that use Qt.
    • Implement QObject subclasses in Rust, which can then be used from C++, QML, and JavaScript.

    The project is split into two main functional parts:

    1. cxx-qt-lib: A library of Rust bindings to common QtCore and QtGui classes built using CXX.
    2. cxx-qt & cxx-qt-build: A pair of Rust and C++ code generators. They extend CXX with additional attributes to interface with Qt's signals & slots and property system.
  3. Learn specific CXX-Qt features through code examples

    main

    The following specific feature implementations are available as standalone examples within the qml_features project:

    • Properties and Invokables: How to define properties and invokables for QML.
    • Signals: How to define and emit signals from Rust.
    • Threading: How to use threaded logic within the CXX-Qt framework.
    • Serialization: How to (de)serialize QObjects.
    • Qt Types: How to use Qt types such as QVariant in Rust.
    • Multiple QObjects: How to define multiple QObjects within a single bridge.
    • Nested Objects: How to implement nested objects.
  4. What is CXX-Qt and how does it work?

    main

    CXX-Qt is a library designed for safe interop between Rust and Qt. Unlike typical one-to-one bindings that attempt to wrap one language's idioms in the other, CXX-Qt uses CXX to bridge between normal Qt code and normal Rust code.

    Core Workflow

    1. Define: The developer describes a QObject using CXX-Qt macro annotations in Rust.
    2. Generate: CXX-Qt uses macros and code generation to create the C++ representation of that object.
    3. Bridge: The library uses macro expansion to define a CXX bridge, enabling safe interop and multi-threading between the two languages.

    To facilitate this, CXX-Qt provides common Qt types for Rust that can be passed across the bridge, allowing Rust code to express common Qt idioms.

  5. Inherit signals from a base class

    main
    If a signal is already defined on the base class of your QObject, you can use the #[inherit] attribute within your extern "RustQt" block. This tells CXX-Qt that the Q_SIGNAL already exists in C++ and does not need to be re-created, allowing your Rust code to access the existing base class signal.
  6. Override base class methods using CXX-Qt attributes

    main

    CXX-Qt allows you to implement C++ inheritance patterns by applying specific attributes to your invokables. This enables Rust methods to be treated as virtual, override, or final in the generated C++ code.

    C++ keywordCXX-Qt attributePurpose
    override#[cxx_override]Implements a virtual method from a base class.
    virtual#[cxx_virtual]Declares a method as virtual so it can be overridden by further subclasses.
    final#[cxx_final]Prevents further overriding of the method.

    Accessing the base implementation when overriding: If you use #[cxx_override], you can still call the original base class implementation by defining a function in an extern "RustQt" block using #[inherit] combined with #[cxx_name]. You must give the Rust function a different name than the overridden method to avoid name collisions in Rust.

  7. Nest QObjects in Rust-Qt properties and parameters

    main

    You can nest Rust-Qt objects by using a pointer to their QObject representation. To achieve this:

    1. Define the type: Include the nested type in an extern block for your bridge as you would for any other type.
    2. Use pointers: Use *mut T in your property definitions, invokable parameters, or signal parameters.

    Important: When using *mut T, T must be the C++ CXX type, not the Rust struct itself.

    To access mutable invokables or property setters on the nested object, you must convert the *mut T pointer to a Pin<&mut T>.

    {{#include ../../../examples/qml_features/rust/src/nested_qobjects.rs:book_macro_code}}
  8. Use the cxx-qt crate for Qt-specific types

    main

    The cxx-qt crate is the primary interface for users. It extends the CXX framework by adding support for the Qt Meta-Object-System. Use it to wrap Qt APIs and create your own Qt-compatible types, including:

    • QObjects
    • QEnums
    • Properties
    • Signals and Slots

    Note that cxx-qt does not wrap the entire Qt API itself; it provides the tools for you to wrap the APIs you need. For common types, use cxx-qt-lib instead.

  9. Use `extern "RustQt"` to declare Qt-specific features

    main

    The extern "RustQt" block within a #[cxx_qt::bridge] module is used to declare Rust types and signatures that should be made available to Qt and C++. This section allows you to define Qt-specific features like QObjects, properties, methods, and signals. The CXX-Qt code generator uses these blocks to produce a C++ header file with a .cxxqt.h extension corresponding to your Rust file name.

    #[cxx_qt::bridge]
    mod ffi {
        extern "RustQt" {
    
        }
    }
  10. How CXX-Qt bridges Rust and C++

    main
    CXX-Qt is built upon CXX, a tool designed to provide safe bridges between Rust and C++. The primary architectural goal of CXX-Qt is to expose Qt's C++ extensions to the CXX bridge, allowing Rust code to interact with Qt's object model and features safely.