API improvements for solving duality of types and related changes #531
Replies: 4 comments
-
Keeping two types seems to be the route for now. |
Beta Was this translation helpful? Give feedback.
-
New suggested API for Signals (also moves cxx_qt::inherit): #[cxx_qt::bridge]
mod ffi {
#[cxx_qt::qobject]
struct MyObject {
}
impl qobject::MyObject {
#[inherit]
#[cxx_name="beginInsertRows"]
fn super_begin_insert_rows(&self);
#[qsignal]
#[inherit]
fn my_signal(&self);
}
} The issue with this right now is mostly that we're unsure whether declaring functions without a function body within an impl block will continue to be passed straight through to our procedural macro... Alternatively, we could explore putting this in an |
Beta Was this translation helpful? Give feedback.
-
Further problem is that So we maybe need to have a "header" portion of invokables, if we want to be able to support #[cxx::bridge]
mod ffi {
extern "Rust" {
fn fallible1(depth: usize) -> Result<String>;
fn fallible2() -> Result<()>;
}
}
fn fallible1(depth: usize) -> anyhow::Result<String> {
if depth == 0 {
return Err(anyhow::Error::msg("fallible1 requires depth > 0"));
}
...
}
fn fallible2() -> Result<(), io::Error> {
...
Ok(())
} |
Beta Was this translation helpful? Give feedback.
-
Suggested API: #[cxxqt::bridge]
mod qobject {
extern "Qt" {
type QAbstractItemModel = cxx_qt_lib::QAbstractItemModel;
type QButton;
type OtherObject = crate::qobject::OtherObject;
#[qsignal]
fn clicked(self: &QButton);
}
extern "RustQt" {
#[base="QAbstractItemModel"]
#[qml_element]
#[qproperty(i32, member="prop")] // needs to access field .prop
#[qproperty(i32, read="get_my_prop", write="set_my_prop")] //#[qproperty(i32, member="prop")]
#[qproperty(QString, read="get_my_prop", write="set_my_prop")] //#[qproperty(QString, member="prop")]
type MyObject = super::MyObject;
#[qinvokable]
fn my_invokable(self: Pin<&mut Self>, ..., *mut OtherObject) -> Result<()>;
#[qsignal]
#[inherit]
fn data(self: Pin<&mut MyObject>, ...) -> ...;
#[cxx_name = "hasChildren"]
#[inherit]
fn has_children_super(self: &MyObject, parent: &QModelIndex) -> bool;
}
impl cxx_qt::Constructor<(i32)> for MyObject {
todo!{}
}
impl cxx_qt::Threading for MyObject {}
// to disable CXXQt locking!
impl !cxx_qt::Locking for MyObject {}
}
struct MyObject {
pub prop: i32,
private_stuff: MySpecialType,
}
impl qobject::MyObject {
fn get_my_prop(&self) -> i32 {
todo!{}
}
fn set_my_prop(self: Pin<&mut Self>, value: i32) {
todo!{}
}
pub fn my_invokable(self: core::pin::Pin<&mut Self>) -> anyhow::Result<()> {
todo! { }
}
} |
Beta Was this translation helpful? Give feedback.
-
Problems
extern "Qt"
- allow signals on existing Qt classes #527qobject
module has no documentation, triggering#![warn(missing_docs)]
#517 Generated documentation doesn't show up on qobject::T #529extern "Qt"
- allow signals on existing Qt classes #527Result<T, E>
and anything where impl Display for T (eganyhow::Result<T>
) as the Rust method return type, but then in the CXX bridge this is written asResult<T>
they do this by writing the API differently in the extern block Support Result<T, E> as a return type from Rust -> C++ #404 https://cxx.rs/binding/result.html#returning-result-from-rust-to-cHigh level solutions
Combining struct and type
If the Rust struct and C++ class happened to have space matching each other they could share the same memory space.
This would mean that we wouldn't need two structs, however
Instead of sharing the exact same memory space there could be a wrapper.
Then MyObject could match the C++ memory space. (is there any advantage to using a Pimpl style thing?)
We would then need to be able to pass through Default constructors on the outer type to the inner, and what would happen with other traits?
We need the dev to only ever be able to access MyObjectInner via a Pin<&mut T> for mut so that we can prevent mutating the field without calling the signal.
Require the dev to be explicit
Instead of hiding the
TQt
type we could instead have the dev write it themselves via a macro attribute or extern block.or
or
These have the advantage of being explicit about another type existing, which make it more obvious where things are coming from.
There are questions over whether the
cxx_name
would rename the type in C++, whether it can be the same as the Rust name, and the same for thetype
variant.The
extern "Qt"
block idea could be combined with the new signals API design, but doesextern "Qt"
refer to Rust or C++ created things, or a shared block ?Summary
So lots of open questions and possible ideas to improve things further.
Either I think we should end up with
Beta Was this translation helpful? Give feedback.
All reactions