White-Oak / qml-rust

QML (Qt Quick) bindings for Rust language
MIT License
205 stars 18 forks source link

add support to return value from slot #33

Open fneddy opened 7 years ago

fneddy commented 7 years ago

is it possible to return Option<QVariant> instead of Option<&QVariant> from a slot? if not we should add support for it to make it possible to return local values.

currently it does not compile:

 pub fn handle_value(&mut self, val: i32 ) ->  Option<QVariant> {
    if val < 0 {
        Some(false.into())
    }
    Some(true.ino())
}
error[E0308]: mismatched types
  --> src/backend.rs:67:1
   |
67 | Q_OBJECT!(
   | ^ expected reference, found struct `qml::QVariant`
   |
   = note: expected type `std::option::Option<&qml::QVariant>`
              found type `std::option::Option<qml::QVariant>`
   = help: here are some functions which might fulfill your needs:
           - .as_ref()
           - .take()
           - .unwrap()
   = note: this error originates in a macro outside of the current crate

error: aborting due to previous error
White-Oak commented 7 years ago

The problem rises from the memory handling -- if it is not a reference, value will take memory and leak it every time this slot will be called

fneddy commented 7 years ago

is this also true for primitive datatypes like i32?

in this case it means there is no feasible way to return results to qml without building a custom garbagecollection-mechanism.

White-Oak commented 7 years ago

@fneddy all primitives are wrapped in QVariants.

Yes, if it's not possible to return a reference, there should be some kind of garbage collector system, which is, hopefully, can be provided via qml-rust to ease memory management.

White-Oak commented 7 years ago

A straightforward way of doing this (I think I made it this way in kefia) is to have some kind of map or list, that returns references to qvariants to qml.

fneddy commented 7 years ago

so I had a little time to investigate:

The slot definition struct has a field for the return type of the slot. In the Q_OBJECT macro this return value is hardcoded to 43 this corresponds to QMetaType::Void.

all primitives are wrapped in QVariants.

this I because is is coded this way. But does it need to be so? The slot definition allows all predefined QMetaTypes as return types.

The problem rises from the memory handling -- if it is not a reference, value will take memory and leak it every time this slot will be called

I think this should be only true for rust structs. QVariant will try to clear the Object but through this are non C++ QObjects this will have no effect an leak(?). All trough for the pre-defined QMetaTypes QVariant should be totally able to free the memory(!?)

So long story short: in my opinion returning a non QVariant should be OK as long as its type is defined as std QMetaType. This way QT should know how to handle free/delete. For every other datatype there must be either a garbage collector or a callback from the QVariant ~destructor that calls the rust struct drop() method.