Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic means to invoke and connect #1035

Closed
SanderVocke opened this issue Aug 15, 2024 · 2 comments
Closed

Generic means to invoke and connect #1035

SanderVocke opened this issue Aug 15, 2024 · 2 comments
Labels
🤔 discussion Feedback welcome

Comments

@SanderVocke
Copy link
Contributor

I noticed that the examples and documentation only provide a means to connect signals to Rust closures/functions.
Likewise, calling slots/invokables seems to be possible only through the bridge-generated Rust entry points.

It would be quite convenient in a mixed codebase to invoke or make connections to any Qt object, even if it was not defined on the Rust side of the bridge. Basically, it means having QMetaObject support, making generic connections between QMetaMethods and being able to pass around QObject handles to operate on.

Is it a design decision to not do such things because QObject handles cannot be guaranteed to be handled safely? Or is this something that might be added down the line?

For now, I am achieving this by having my own QObject type with C++-side helper methods, which I can pass around / connect to / invoke on via bridged C++ methods. This does mean I am having to mark lots of code unsafe and passing around a lot of *mut QObject handles.

@ahayzen-kdab
Copy link
Collaborator

So we do have a "new" extern "C++Qt" which allows you to describe an existing Qt object https://kdab.github.io/cxx-qt/book/bridge/extern_cppqt.html

The idea of this is that there is an existing type in C++ that has signals/invokables and you would write this code to then express that there is a signal and then you can create connections from it on the Rust side.

#[cxx_qt::bridge]
mod ffi {
    extern "C++Qt" {
        include!(<QtWidgets/QPushButton>);
        type QPushButton;

        #[qsignal]
        fn clicked(self: Pin<&mut QPushButton>, checked: bool);
    }
}

Now to answer your questions directly...

  • (Rust signals are only connected to closures), yes at the moment it is only possible to use closures as it's very tricky to get the type of the Rust function across the CXX bridge through to C++ to do a direct connection between methods like in normal Qt. For now on the Rust side you need to use a closure or create a method/invokable and then connect to it in C++/QML. Maybe we can figure out a way but it seems tricky for now and most usecases are fine with a closure
  • (QObject/QMetaObject bases etc) So what we are looking at doing is implementing a trait for any type defined as a #[qobject] either in C++Qt / RustQt that would then allow you to cast to the QObject* and then if we have QObject already in cxx-qt-lib you'd have a lot of the functionality already existing. There are also discusisons around general up/down casting of the types (eg to go from MyObject -> QAbstractListModel or from QObject to MyObject etc). Most of these discussions are in Traits for CxxQtType/QtObject #562
  • (generics) In general generics are very hard with CXX you tend to need to make a specific bridge method for each concrete type (as you can see in our Qt containers / QVariant implementation in cxx-qt-lib)
  • (unsafety of ptr) Yes it is generally unfortunate that Qt for historical reasons passes things around as raw pointers rather than using shared pointer or unique pointer, as those are then safe in CXX

Maybe once #562 is available you would be able to easily cast / reach the QMetaObject or get from a QObject* and test if you can downcast to MyObject*.

As then you could have like Pin<&mut QObject> or QObject* as an input type to methods, cxx-qt-lib could have most of the functions of QObject implemented so that you can already use things like children() etc (rather than you having to define QObject yourself in a CXX bridge). And then you could downcast from the QObject* to MyObject*.

Also note we have a Zulip chat if you want to have longer discussions on things :-) https://cxx-qt.zulipchat.com/

@ahayzen-kdab ahayzen-kdab added the 🤔 discussion Feedback welcome label Aug 15, 2024
@SanderVocke
Copy link
Contributor Author

Thanks! That effort for QtObject traits seems to go exactly where I am hoping.

I am currently taking a similar approach in my own codebase by having my own traits for QObject an QQuickItem, plus some C++-side templates that can be pulled in on-demand for connect and invoke calls.

I will close this though, seems it is clearly already being worked on!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤔 discussion Feedback welcome
Projects
None yet
Development

No branches or pull requests

2 participants