dbus2 / zbus-old

Rust D-Bus crate.
https://gitlab.freedesktop.org/dbus/zbus
Other
49 stars 13 forks source link

Issue when returning a struct from an interface method #232

Closed zeenix closed 1 year ago

zeenix commented 2 years ago

In GitLab by @DataTriny on Nov 17, 2021, 19:22

Consider this example program:

use serde::{Deserialize, Serialize};
use zbus::{blocking::Connection, dbus_interface};
use zvariant::derive::Type;

#[derive(Deserialize, Serialize, Type)]
struct MyStruct {
    value1: String,
    value2: String,
}

struct MyIface;

#[dbus_interface(name = "org.zbus.MyIface")]
impl MyIface {
    fn get_struct(&self) -> MyStruct {
        MyStruct {
            value1: "One".into(),
            value2: "Two".into()
        }
    }
}

fn main() {
    let conn = Connection::session().unwrap();
    conn.request_name("org.zbus.Test").unwrap();
    conn.object_server_mut().at("/org/zbus/test", MyIface).unwrap();
    loop {}
}

Calling this server like so:

busctl --user call org.zbus.Test /org/zbus/test org.zbus.MyIface GetStruct

Results in this reply:

ss "One" "Two"

Which I think is a bug. Here is the introspection data:

busctl --user introspect org.zbus.Test /org/zbus/test org.zbus.MyIface
NAME             TYPE      SIGNATURE RESULT/VALUE FLAGS
.GetStruct       method    -         (ss)         -

A struct should clearly be returned. To achieve proper behavior, I have to modify the method like this:

fn get_struct(&self) -> (MyStruct,) {
    (MyStruct {
        value1: "One".into(),
        value2: "Two".into()
    },)
}

Which is ugly and shouldn't be necessary according to the documentation.

zeenix commented 2 years ago

@DataTriny There is a special attribute (struct_return) for returning structs:

struct_return - the method returns a structure. Although it is very rare for a D-Bus method to return a single structure, it does happen. Since it is not possible for zbus to differentiate this case from multiple out arguments put in a structure, you must either explicitly mark the case of single structure return with this attribute or wrap the structure in another structure or tuple. The latter can be achieve by using (,) syntax, for example instead of MyStruct, write (MyStruct,).

Please re-open if you've any ideas on how we can handle this better.

zeenix commented 2 years ago

Thanks for reporting this still though and providing a complete example. It's still appreciated. :smiley_cat:

zeenix commented 2 years ago

In GitLab by @DataTriny on Nov 19, 2021, 17:44

Hi @zeenix ,

My bug report may have been detailed, it however lacked a very important information: I am using zbus version 2.0.0-beta.7.

Here is the bit of documentation I was referring to:

struct_return - This attribute is depcrecated and a noop. If you want to return a single structure from a method, simply declare it to return a named structure or a tuple with a tuple as the only field.

The long and somewhat hard to understand sentence that follows only adds to the confusion. Is it simply a documentation error then?

zeenix commented 2 years ago

My bug report may have been detailed, it however lacked a very important information: I am using zbus version 2.0.0-beta.7.

Oh, I forgot that we changed that.

struct_return - This attribute is depcrecated and a noop. If you want to return a single structure from a method, simply declare it to return a named structure or a tuple with a tuple as the only field.

The long and somewhat hard to understand sentence that follows only adds to the confusion. Is it simply a documentation error then?

The docs say exactly what you're observing so if it's confusing, then yes, that's the issue. I recall now that I had trouble wording it well. If you can suggest better wording, that'd be very useful indeed. A merge-request would be best of course but it's ok to just write it here and I'll update the doc comment once we both agree on it. :)

zeenix commented 2 years ago

mentioned in commit 1d11ebdaf979f22d3a0121eb11a309b31551cd12