diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index e2648b9bf..664a94664 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -119,7 +119,14 @@ impl GeneratedRustFragment { unsafe fn upcast_ptr(this: *const Self) -> *const #base_qualified { #upcast_fn_qualified(this) } + + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None //TODO! placeholder, use the right dynamic_cast function + } } + }, + quote! { + impl ::cxx_qt::Downcast for #struct_name {} }], ======= implementation: vec![ diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index 20be1cda4..be02907a0 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -89,7 +89,11 @@ impl ::cxx_qt::Upcast for inheritance::MyObject unsafe fn upcast_ptr(this: *const Self) -> *const inheritance::QAbstractItemModel { inheritance::cxx_qt_ffi_MyObject_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for inheritance::MyObject {} #[doc(hidden)] pub fn create_rs_MyObjectRust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index 681cbf651..99e588ad1 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -307,7 +307,11 @@ impl ::cxx_qt::Upcast<::cxx_qt::qobject::QObject> for ffi::MyObject { unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::qobject::QObject { ffi::cxx_qt_ffi_MyObject_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::MyObject {} #[doc(hidden)] pub fn route_arguments_MyObject_0<'a>( arg0: i32, diff --git a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs index 64448c7d6..8b5919be2 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -612,7 +612,11 @@ impl ::cxx_qt::Upcast for ffi::MyObject { unsafe fn upcast_ptr(this: *const Self) -> *const ffi::QStringListModel { ffi::cxx_qt_ffi_MyObject_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::MyObject {} #[doc(hidden)] pub fn create_rs_MyObjectRust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) @@ -782,7 +786,11 @@ impl ::cxx_qt::Upcast<::cxx_qt::qobject::QObject> for ffi::SecondObject { unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::qobject::QObject { ffi::cxx_qt_ffi_SecondObject_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::SecondObject {} #[doc(hidden)] pub fn create_rs_SecondObjectRust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) @@ -806,7 +814,11 @@ impl ::cxx_qt::Upcast<::cxx_qt::qobject::QObject> for ffi::MyRustName { unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::qobject::QObject { ffi::cxx_qt_ffi_MyCxxName_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::MyRustName {} #[doc(hidden)] pub fn create_rs_ThirdObjectRust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index d55ca4caf..7e47842a7 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -1051,7 +1051,11 @@ impl ::cxx_qt::Upcast<::cxx_qt::qobject::QObject> for ffi::MyObject { unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::qobject::QObject { ffi::cxx_qt_ffi_MyObject_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::MyObject {} #[doc(hidden)] pub fn create_rs_MyObjectRust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) diff --git a/crates/cxx-qt-gen/test_outputs/qenum.rs b/crates/cxx-qt-gen/test_outputs/qenum.rs index 95804aac1..88f4e072f 100644 --- a/crates/cxx-qt-gen/test_outputs/qenum.rs +++ b/crates/cxx-qt-gen/test_outputs/qenum.rs @@ -164,7 +164,11 @@ impl ::cxx_qt::Upcast<::cxx_qt::qobject::QObject> for ffi::MyObject { unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::qobject::QObject { ffi::cxx_qt_ffi_MyObject_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::MyObject {} #[doc(hidden)] pub fn create_rs_MyObjectRust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) @@ -188,7 +192,11 @@ impl ::cxx_qt::Upcast<::cxx_qt::qobject::QObject> for ffi::MyRenamedObject { unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::qobject::QObject { ffi::cxx_qt_ffi_CxxName_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::MyRenamedObject {} #[doc(hidden)] pub fn create_rs_InternalObject() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index 35a845ba2..a784749db 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -442,7 +442,11 @@ impl ::cxx_qt::Upcast<::cxx_qt::qobject::QObject> for ffi::MyObject { unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::qobject::QObject { ffi::cxx_qt_ffi_MyObject_upcastPtr(this) } + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self> { + None + } } +impl ::cxx_qt::Downcast for ffi::MyObject {} #[doc(hidden)] pub fn create_rs_MyObjectRust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) diff --git a/crates/cxx-qt/include/casting.h b/crates/cxx-qt/include/casting.h index 77d4223d2..f285f2cb9 100644 --- a/crates/cxx-qt/include/casting.h +++ b/crates/cxx-qt/include/casting.h @@ -15,4 +15,6 @@ upcastPtr(const Sub* sub) return static_cast(sub); } +// TODO! add base_ptr downcasting function here + } diff --git a/crates/cxx-qt/src/lib.rs b/crates/cxx-qt/src/lib.rs index d92ab45b2..1e35a0237 100644 --- a/crates/cxx-qt/src/lib.rs +++ b/crates/cxx-qt/src/lib.rs @@ -132,6 +132,10 @@ pub trait Upcast { /// Internal function, Should not be implemented manually unsafe fn upcast_ptr(this: *const Self) -> *const T; + #[doc(hidden)] + /// Internal function, Should not be implemented manually + unsafe fn from_base_ptr(base: *const T) -> Option<*const Self>; + /// Upcast a reference to a reference to the base class fn upcast(&self) -> &T { let ptr = self as *const Self; @@ -160,6 +164,14 @@ pub trait Upcast { } } +/// Trait for downcasting to a subclass, provided the subclass implements Upcast to this type +pub trait Downcast: Sized { + /// Downcast to a subclass of this, given that the subclass upcasts to this type + fn downcast>(&self) -> Option<&Sub> { + unsafe { Sub::from_base_ptr(self as *const Self).map(|sub| &*sub) } + } +} + /// This trait can be implemented on any [CxxQtType] to define a /// custom constructor in C++ for the QObject. ///