qmlrs icon indicating copy to clipboard operation
qmlrs copied to clipboard

calling QML from Rust

Open kirillkh opened this issue 9 years ago • 15 comments

Is it possible to call QML functions from Rust?

kirillkh avatar Jun 23 '15 19:06 kirillkh

The proper way to do this would be to support defining signals on the Rust side; the C++ wrapper library already supports this and the Rust side also once upon a time used to support them, but the implementation was horrible hack that mungled with internal Rust representations and was not memory safe either.

So not really right now, but it could be implemented. The hard part is making a nice and safe Rust interface for signals.

cyndis avatar Jun 24 '15 07:06 cyndis

Well, it seems to me a lot of functionality is missing when you can't communicate with the GUI from your rust code. My project certainly needs this.

kirillkh avatar Jun 24 '15 07:06 kirillkh

Yes, that is true. Unfortunately the time I have been able to spend on this project lately has been very low.

cyndis avatar Jun 24 '15 07:06 cyndis

I'd be willing to implemented it if I knew what's the problem with the current solution. Looking at the commented-out code signals are identified by their signature via string comparison and invoked using QMetaObject::activate on the C++ side. That's pretty much the same what go-qml and pyside does.

flanfly avatar Jul 06 '15 12:07 flanfly

There are a couple of issues, nothing really fundamental. Mostly figuring out how to present things in a safe way.

  1. How to emit a signal from code? How would the Rust code get ahold of a *mut QObject to emit a signal from. The current code in lib.rs uses PropHdr which kind of works but is horribly unsafe, since there's nothing to prevent the user from copying his data somewhere else. If the user does that, the copy will still be T: Object but it will not be inside a PropHdr.
  2. How would the Rust code get ahold of a &T where T: Object. Currently add_property consumes the object which means that only a slot can emit a signal which isn't very useful.
  3. How would signals be declared in Rust code. The Q_OBJECT macro used to work but was broken during stabilization changes before 1.0. I'm not a macro expert, though, so there might be a workaround. The macro will likely require an overhaul anyway to be able to support things like lifetime parameters. To get rid of PropHdr we might also need to change the data layout such that the user's type will contain some reference to the backing *mut QObject.

Thanks :)

cyndis avatar Jul 06 '15 13:07 cyndis

Any news on this? I need to be able to send signals from Rust in my project

bgdncz avatar Oct 01 '15 14:10 bgdncz

I extended qmlrs to allow emitting signals in Rust code as well as defining singleton type that allows QML code to call Rust functions.

The code isn't really PR-ready. I ignore thread-safety completely, the Q_OBJECT! macro is broken and I don't know if the API is usable outside of my limited use-case.

You can take a look on it here: https://github.com/das-labor/panopticon/blob/master/qt/src/controller.rs

flanfly avatar Oct 01 '15 21:10 flanfly

Hi everyone, i'm the author of the DOtherSide C++ library that basically implements a C layer for creating bindings to the Qml layer. I developed the DQml and NimQml bindings. Maybe we can work together by porting your C++ code to my library. In this way we can arrive at a common implementation for Nim, D and Rust. Furthermore i find it stupid to rewrite the C++ part. Btw the DOtherSide project already support creation of singletons, custom types, signals, slots. You should just call the C functions for having the work done. :)

filcuc avatar Apr 28 '16 21:04 filcuc

https://github.com/filcuc/DOtherSide

filcuc avatar Apr 28 '16 21:04 filcuc

Do you think it's possible to have safe Rust code work with your OtherSide implementation?

colms avatar Apr 30 '16 09:04 colms

It depends on what do you mean with safe. I'm not a rust expert and i just slightly know the language but i don't think that it's possible to call C functions outside unsafe blocks. Given that, my library tries to be as safe as possible, for example right now i'm preventing accessing QObjects instantiated by someone different than the binded language. If you want to do such kind of things do that in QML. Regarding the thread safety my library doesn't do any assumption: it's up to the binded language to decide how to handle threading (keeping in mind that anything that mess with the UI should be done by the UI thread [ that should be the main thread]).

2016-04-30 11:28 GMT+02:00 colms [email protected]:

Do you think it's possible to have safe Rust code work with your C++ implementation?

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/cyndis/qmlrs/issues/22#issuecomment-215949023

Filippo Cucchetto

filcuc avatar Apr 30 '16 12:04 filcuc

@filcuc I was intending to rewrite qmlrs based on libqmlbind, see #22 for the discussion. I was not aware that there is a competitor to libqmlbind, though.

Is there any documentation for DOtherSide, especially on how it can be used from a library author's point of view? I can't find any, so it's hard for me to spot the differences between DOtherSide and libqmlbind. Or could you compare DOtherSide to libqmlbind?

(libqmlbind's documentation can be found at https://seanchas116.github.io/libqmlbind/)

In any case, I'll list DOtherSide as an alternative to libqmlbind: https://github.com/seanchas116/libqmlbind/pull/40

florianjacob avatar May 10 '16 12:05 florianjacob

@colms A safe Rust interface will be possible regardless of the underlying backend library. :smile: That's the main job of qmlrs if you take the C wrapper away - creating a safe rust interface without exposing the unsafeness of the used C functions. :wink:

florianjacob avatar May 10 '16 12:05 florianjacob

@florianjacob @colms as long as the C library is "safe" :D

@florianjacob Probably i cant' convince you in anyway in adopting my library over libqmlbind since you seems to be a strong contributor but i'll try to answer to your questions:

Is there any documentation for DOtherSide? how it can be used from a library author's point of view

We've two complete bindings in place DQml and NimQml. The logic is more or less the same in both bindings. I think that there's no better example that a full binding for a different language. The library aim to be small and expose only the needed stuff for making full databound applications. So it doesn't expose any QObject* that wasn't created by the bindings. All the api's are in 1 single file of 150 lines.

Or could you compare DOtherSide to libqmlbind?

From the outside they're very similar if not identical. Both are

  • portable. At the time of writing the DOtherSide is automatically packaged for Windows and Linux but it has already been built successfully for Mac by some users.
  • small
  • use similar conventions _create (_new) _delete (_release)

On the other hand i don't know the internals but i can guess that they both works the same more or less.

For the rest the DOtheSide library:

  • Already support QAbstractItemModels
  • Support QML Singletons
  • Support instantions of custom QObjects defined in the binded language from QML. So you can create custom QML types.
  • Proved to work with two different languages and by improving the underlying library all the bindings could benefit and improve. Rust could be a further prove that the design works
  • DOtherSide was started before libqmlbind

filcuc avatar May 10 '16 18:05 filcuc

Support for QAbstractItemModels in qmlrs would be very welcome. It can be emulated a bit by populating a ListModel via JavaScript that calls into Rust.

vandenoever avatar May 23 '16 13:05 vandenoever