Skip to content

Commit ed8552b

Browse files
BenFordTytheringtonahayzen-kdab
authored andcommitted
Update book and docs
1 parent 39e86e7 commit ed8552b

File tree

5 files changed

+75
-13
lines changed

5 files changed

+75
-13
lines changed

book/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0
2121
- [Types](./concepts/types.md)
2222
- [Nested Objects](./concepts/nested_objects.md)
2323
- [Inheritance & Overriding](./concepts/inheritance.md)
24+
- [Casting](./concepts/casting.md)
2425
- [Reference: the bridge module](./bridge/index.md)
2526
- [`extern "RustQt"`](./bridge/extern_rustqt.md)
2627
- [`extern "C++Qt"`](./bridge/extern_cppqt.md)

book/src/bridge/extern_rustqt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Use the CXX `include!` macro to include the appropriate C++ header for the base
9292
{{#include ../../../examples/qml_features/rust/src/custom_base_class.rs:book_base_include}}
9393
```
9494

95-
For more information on inheritance and how to override methods see the [Inheritance & Overriding](../concepts/inheritance.md) page.
95+
For more information on inheritance and how to override methods see the [Inheritance & Overriding](../concepts/inheritance.md) page and the [Casting](../concepts/casting.md) page.
9696

9797
[Full Example](https://github.com/KDAB/cxx-qt/blob/main/examples/qml_features/rust/src/custom_base_class.rs)
9898

book/src/bridge/traits.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ For further documentation, refer to the documentation of the individual traits:
2626
- [Constructor](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Constructor.html) - custom constructor
2727
- [Initialize](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Initialize.html) - execute Rust code when the object is constructed
2828
- [Threading](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Threading.html) - marker trait whether CXX-Qt threading should be enabled
29+
30+
> ⚠️ These traits should only be implemented if you are sure you need to, they are automatically implemented for RustQt types.
31+
32+
- [Upcast](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Upcast.html) - Allows a type to access its parent class if there is one
33+
- [Downcast](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Downcast.html) - Allows a type to access its child class if there is one

book/src/concepts/casting.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
3+
SPDX-FileContributor: Ben Ford <[email protected]>
4+
5+
SPDX-License-Identifier: MIT OR Apache-2.0
6+
-->
7+
8+
# Casting
9+
10+
With the [base](../bridge/attributes.md) attribute, it is possible to inherit from another type.
11+
In order to access this parent class, we provide an API to cast up or down.
12+
Currently, this is only supported for objects in `extern "RustQt"` blocks, which have either a `#[qobject]` attribute,
13+
or a `#[base = T]` attribute. see [here](../bridge/attributes.md) for more details on these attributes.
14+
15+
## Accessing the base class
16+
17+
To access the methods of a base class in Rust, use the `Upcast` trait like so `use cxx_qt::Upcast;`.
18+
Objects with base classes can then be accessed with the following methods
19+
20+
| Self Type | Method |
21+
|------------------|----------------|
22+
| `&self` | `upcast()` |
23+
| `&mut self` | `upcast_mut()` |
24+
| `Pin<&mut self>` | `upcast_pin()` |
25+
26+
This will then return a reference to the base in the same format as the self type, e.g. `upcast()` returns `&Base`, etc...
27+
28+
## Accessing the child class
29+
30+
This also works in the opposite direction, allowing access to the child a base class was obtained from.
31+
To do this, use the `Downcast` trait like so `use cxx_qt::Downcast;`.
32+
The child can then be accessed in the same manner, with the following methods
33+
34+
| Self Type | Method |
35+
|------------------|------------------|
36+
| `&self` | `downcast()` |
37+
| `&mut self` | `downcast_mut()` |
38+
| `Pin<&mut self>` | `downcast_pin()` |
39+
40+
These will return an `Option<T>`, as it is possible that downcasting will fail,
41+
if the type is not actually of the given subclass,
42+
and these also return in the same format as the self type, e.g. `downcast()` returns `Option<&Sub>`, etc...

crates/cxx-qt/src/lib.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -127,19 +127,30 @@ pub trait Threading: Sized {
127127
fn threading_drop(cxx_qt_thread: &mut CxxQtThread<Self>);
128128
}
129129

130-
/// This trait is automatically implemented by CXX-Qt and should not be manually implemented
131-
/// Allows upcasting to either QObject or the provided base class of a type
132-
/// Will not be implemented if no types inherit from QObject or base.
130+
/// This trait is automatically implemented by CXX-Qt and you most likely do not need to manually implement it.
131+
/// Allows upcasting to either [QObject] or the provided base class of a type.
132+
/// Will not be implemented if no types inherit from [QObject] or have the `#[base = T]` attribute.
133133
pub trait Upcast<T> {
134134
#[doc(hidden)]
135-
/// Internal function, Should not be implemented manually
135+
/// # Safety
136+
///
137+
/// Internal function, Should probably not be implemented manually unless you're absolutely sure you need it.
138+
/// Automatically available for types in RustQt blocks in [cxx_qt::bridge](bridge)s.
139+
/// Upcasts a pointer to `Self` to a pointer to the base class `T`.
140+
/// > Note: Internal implementation uses `static_cast`.
136141
unsafe fn upcast_ptr(this: *const Self) -> *const T;
137142

138143
#[doc(hidden)]
139-
/// Internal function, Should not be implemented manually
144+
/// # Safety
145+
///
146+
/// Internal function, Should probably not be implemented manually unless you're absolutely sure you need it.
147+
/// Automatically available for types in RustQt blocks in [cxx_qt::bridge](bridge)s.
148+
/// Downcasts a pointer to base class `T` to a pointer to `Self`.
149+
/// Return a null pointer if `Self` is not actually a child of base.
150+
/// > Note: Internal implementation uses `dynamic_cast`.
140151
unsafe fn from_base_ptr(base: *const T) -> *const Self;
141152

142-
/// Upcast a reference to a reference to the base class
153+
/// Upcast a reference to self to a reference to the base class
143154
fn upcast(&self) -> &T {
144155
let ptr = self as *const Self;
145156
unsafe {
@@ -148,7 +159,7 @@ pub trait Upcast<T> {
148159
}
149160
}
150161

151-
/// Upcast a mutable reference to a mutable reference to the base class
162+
/// Upcast a mutable reference to sell to a mutable reference to the base class
152163
fn upcast_mut(&mut self) -> &mut T {
153164
let ptr = self as *const Self;
154165
unsafe {
@@ -157,7 +168,7 @@ pub trait Upcast<T> {
157168
}
158169
}
159170

160-
/// Upcast a pinned mutable reference to a pinned mutable reference to the base class
171+
/// Upcast a pinned mutable reference to self to a pinned mutable reference to the base class
161172
fn upcast_pin(self: Pin<&mut Self>) -> Pin<&mut T> {
162173
let this = self.deref() as *const Self;
163174
unsafe {
@@ -167,9 +178,11 @@ pub trait Upcast<T> {
167178
}
168179
}
169180

170-
/// Trait for downcasting to a subclass, provided the subclass implements Upcast to this type
181+
/// This trait is automatically implemented by CXX-Qt and you most likely do not need to manually implement it.
182+
/// Trait for downcasting to a subclass, provided the subclass implements [Upcast] to this type.
183+
/// Returns `None` in cases where `Sub` isn't a child class of `Self`.
171184
pub trait Downcast: Sized {
172-
/// try Downcast to a subclass of this, given that the subclass upcasts to this type
185+
/// Try to downcast to a subclass of this type, given that the subclass upcasts to this type
173186
fn downcast<Sub: Upcast<Self>>(&self) -> Option<&Sub> {
174187
unsafe {
175188
let ptr = Sub::from_base_ptr(self as *const Self);
@@ -181,7 +194,7 @@ pub trait Downcast: Sized {
181194
}
182195
}
183196

184-
/// try Downcast mutably to a subclass of this, given that the subclass upcasts to this type
197+
/// Try to downcast mutably to a subclass of this, given that the subclass upcasts to this type
185198
fn downcast_mut<Sub: Upcast<Self>>(&mut self) -> Option<&mut Sub> {
186199
unsafe {
187200
let ptr = Sub::from_base_ptr(self as *const Self) as *mut Sub;
@@ -193,7 +206,7 @@ pub trait Downcast: Sized {
193206
}
194207
}
195208

196-
/// try Downcast a pin to a pinned subclass of this, given that the subclass upcasts to this type
209+
/// Try to downcast a pin to a pinned subclass of this, given that the subclass upcasts to this type
197210
fn downcast_pin<Sub: Upcast<Self>>(self: Pin<&mut Self>) -> Option<Pin<&mut Sub>> {
198211
let this = self.deref() as *const Self;
199212
unsafe {
@@ -207,6 +220,7 @@ pub trait Downcast: Sized {
207220
}
208221
}
209222

223+
/// Automatic implementation of Downcast for any applicable types
210224
impl<T: Sized> Downcast for T {}
211225

212226
/// This trait can be implemented on any [CxxQtType] to define a

0 commit comments

Comments
 (0)