Skip to main content

Crate qtbridge_interfaces

Crate qtbridge_interfaces 

Source
Expand description

§Qt Interfaces (Internal Documentation)

This crate provides proxies for various Qt (C++) interfaces using Cxx. Proxies serve as the bridge between Rust and C++ implementations of Qt interfaces, allowing Rust types to implement behavior expected by C++ code and to access C++ functionality from Rust.

§The proxy

Each Qt interface has a corresponding proxy in Rust. This proxy has to implement the qtbridge_runtime::qproxies::QRustProxy trait and interacts mostly with the [qtbridge_runtime::QObjectHolder] trait, that is automatically implemented for all user types by the qobject macro.

The demands on proxies are baked into the qtbridge_runtime::qproxies::QRustProxy trait. For example, there is the demand to provide a Qt static meta object, usually from the “base” this proxy is derived from. Further, the proxy has to provide a marker trait called AdapterType that is at a minimum used to store a reference to the user object as Rc<RefCell<dyn AdapterType>>. Otherwise the proxy is mostly free in its design.

All proxies provided in this module follow a similar architecture. The proxy works together with a set of traits. The QObject proxy is very different since it is the proxy that is used if only QMetaObject functionality needs to be provided but no interface implementation.

§Traits

  1. User-implemented functionality: Rust implementations of Qt virtual functions.
  2. Rust access to C++ functionality: Rust wrappers around C++ methods of the interface.
  3. Internal type erasure and proxy plumbing: Allows dynamic behavior when types are not fully known at compile time.

These proxies rely on the following Rust traits to define functionality and structure, shown on the example of QListModel.

§1. QListModel

  • Responsibility: Must be implemented by the user.
  • Purpose: Functions in this trait are called from C++ via the proxy, providing Rust implementations of Qt virtual functions. Some modifications can be done in the functions to shape the API and to erase Qt types (e.g. QVariant and QModelIndex).
  • Associated Types: Defines types (e.g., Item) that are part of the interface contract.
  • Notes: Users implement function as expected from the Qt API. Default implementation can exist for non-pure virtual functions.

§2. QListModelBase

  • Responsibility: Default / blank implementation for all QListModel.
  • Purpose: Provides access to C++ functions from Rust and other convenience functions that should not be overridden. Serves as a bridge between user logic and C++ functionality. Functions that should not be overridden by the user are implemented here.
  • Notes: This trait forms the core Rust interface to call C++ functions for types implementing QListModel.

§3. QListModelAdapter (Internal Only)

  • Responsibility: Default / blank implementation for all QListModel.
  • Purpose: Provides a type-erased interface for internal machinery. Traits with associated types (like QListModel::Item) cannot be used as dyn traits in Rust. QListModelAdapter erases unknown types while exposing the necessary interface internally.
  • Notes: Never meant for user implementation or usage. Facilitates dynamic behavior and internal bridging without exposing associated types to user code.

§Memory Ownership and Lifetimes

Every instance of a user-defined Rust struct annotated with #[qobject] has two auxiliary parts invisible to the user:

  • CppProxy - a C++ class derived from QObject or QAbstractItemModel (or another base interface). This is the object the QML engine sees and interacts with. It is allocated with a regular new for Rust-created objects, or with placement new at a QML-engine-supplied address for QML-created elements.
  • RustProxy - the Rust-side bridge, heap-allocated via Box::into_raw in QRustProxy::new. It holds a pointer to CppProxy and, in RustObjAccess, the strong Rc<RefCell<UserStruct>> that keeps the user struct alive.

A user struct therefore lives exactly as long as its QObject, plus any user handles, which are plain Rc<RefCell<UserStruct>>s. There is one teardown chain, no matter who initiates the deletion:

QObject dies (the engine, a parent, or registry::collect_garbage())
  → virtual ~CppProxy()
    → GenericRustProxy::drop_self
      → on_drop() (removes the registry entry)
      → RustProxy drops its Rc
        → UserStruct::drop()          (only if this was the last strong Rc)

Who may initiate the deletion is the registry’s policy: the per-entry owner state, the CppOwnership pin for Rust-created objects, and the collection rules live in qtbridge_runtime::registry.

Re-exports§

pub use qabstract_item_model::QAbstractItemModel;
pub use qabstract_item_model::QAbstractItemModelBase;
pub use qlist_model::QListModel;
pub use qlist_model::QListModelBase;
pub use qparser_status::QParserStatus;
pub use qtable_model::QTableModel;
pub use qtable_model::QTableModelBase;
pub use object_access::rust_object_access::RustObjAccess;

Modules§

genericrustproxy
object_access
qabstract_item_model
qlist_model
qobject
qparser_status
qtable_model

Macros§

call_cpp_impl
call_rust_trait_impl
impl_qcpp_proxy

Functions§

live_proxy_count
The number of objects the registry currently owns. Useful for leak checks.