Skip to content
This repository has been archived by the owner on Jun 8, 2021. It is now read-only.

Generate D-Bus classes #303

Merged
merged 1 commit into from
Jun 4, 2020
Merged

Generate D-Bus classes #303

merged 1 commit into from
Jun 4, 2020

Conversation

valpackett
Copy link
Contributor

@valpackett valpackett commented Jun 2, 2020

That was easy enough, even extracting the method invocation object in the Closure just worked :)

the "unused import: glib::translate" is annoying though

Example code
    use gio::ApplicationExt;
    let app = gio::Application::new(Some("org.gtk-rs.Test"), gio::ApplicationFlags::default());
    app.register::<gio::Cancellable>(None).unwrap();
    let bus = app.get_dbus_connection().unwrap();

    // Plain call
    let result = bus.call_future(
        Some("org.gnome.Lollypop"), "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player",
        "PlayPause", None, None, gio::DBusCallFlags::NONE, 69).await;
    eprintln!("{:?}", result);

    // Proxy
    use gio::DBusProxyExt;
    let proxy = gio::DBusProxy::new_future(
        &bus, gio::DBusProxyFlags::NONE, None,
        Some("org.gnome.Lollypop"), "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player"
        ).await.unwrap();
    let result = proxy.call_future(
        "PlayPause", None, gio::DBusCallFlags::NONE, 69).await;
    eprintln!("{:?}", result);

    // Server (v2_46)
    let intf_info = gio::DBusNodeInfo::new_for_xml(r#"
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
	<interface name="org.gtk_rs.Thingy">
		<method name="Hello">
			<arg name="name" type="s" direction="in"/>
		</method>
	</interface>
</node>
"#).unwrap().lookup_interface("org.gtk_rs.Thingy").unwrap();
    bus.register_object_with_closures(
        "/org/gtk_rs/Thingy", &intf_info,
        Some(&glib::Closure::new(|args| {
            let mut iter = args.iter();
            let _ = iter.next(); // GDBusConnection
            eprintln!("uniq {:?}", iter.next().unwrap().get::<String>());
            eprintln!("path {:?}", iter.next().unwrap().get::<String>());
            eprintln!("intf {:?}", iter.next().unwrap().get::<String>());
            eprintln!("meth {:?}", iter.next().unwrap().get::<String>());
            eprintln!("args {:?}", iter.next().unwrap().get::<glib::Variant>().unwrap().unwrap());
            let invo = iter.next().unwrap().get::<gio::DBusMethodInvocation>().unwrap().unwrap();
            invo.return_value(None);
            None
        })),
        None,
        None).unwrap();

Screen_2020-06-02-16:43:42

@GuillaumeGomez
Copy link
Member

That's a great start! I think a lot of small things will need to be updated but at least it has been started, thank you for that!

src/auto/functions.rs Outdated Show resolved Hide resolved

glib_wrapper! {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DBusArgInfo(Shared<gio_sys::GDBusArgInfo>);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not useful as it is. Needs some accessors for the struct fields manually implemented, same for DbusPropertyInfo and DbusMethodInfo and all those other Info structs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main use of Info structs is to do gio::DBusNodeInfo::new_for_xml, .lookup_interface and pass the DBusInterfaceInfo to register_object_with_closures :)

Actual inspection of info would be nice I guess, but not a priority for me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like much is missing for that though, just the field accessors or not?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(should create an issue about that so it can be added later and is not forgotten if you don't want to add it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing is missing, you can see I'm using it in the example in the first post here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I mean inspection is missing, and the struct accessors for these Info structs seem to be the only thing missing for that :)

You're right that it can actually also be used otherwise like you did via the XML, I hadn't thought of that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add these once this one is merged here

@sdroege
Copy link
Member

sdroege commented Jun 2, 2020

Overall looks quite nice, thanks :) It's all rather low-level (like the C API is) but could be wrapped in a nicer higher-level API on top of this for something more convenient.

}

impl<O: IsA<DBusInterface>> DBusInterfaceExt for O {
fn dup_object(&self) -> Option<DBusObject> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dup_object() should be renamed to get_object(), and get_object() be hidden. get_object() is not safe, see the docs, and otherwise equivalent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh I'm not sure about the "rename" part. Don't like it when bindings are that unfaithful to the original library :D

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a bindings point of view both functions work exactly the same, and both are "dup"licating (i.e. g_object_ref()) the return value. Just that the get() variant is internally unsafe while the dup() one is not (the get() one was a API design bug from what I understand).

So we definitely don't want to expose the get() variant, and as dup() makes semantically no sense for the bindings renaming it to get() would seem better and less confusing for users :)

src/auto/functions.rs Outdated Show resolved Hide resolved
src/auto/functions.rs Outdated Show resolved Hide resolved
src/auto/functions.rs Outdated Show resolved Hide resolved
src/auto/functions.rs Outdated Show resolved Hide resolved
src/auto/dbus_connection.rs Outdated Show resolved Hide resolved
src/auto/dbus_connection.rs Outdated Show resolved Hide resolved
src/auto/dbus_connection.rs Outdated Show resolved Hide resolved
src/auto/dbus_connection.rs Outdated Show resolved Hide resolved
src/auto/dbus_connection.rs Outdated Show resolved Hide resolved
src/auto/dbus_connection.rs Outdated Show resolved Hide resolved
Copy link
Member

@sdroege sdroege left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went through everything in detail now. Lots of little things but generally looks good :)

@sdroege
Copy link
Member

sdroege commented Jun 3, 2020

Proper use of this API will also need gtk-rs/glib#113 to be solved so more than trivial types can be passed via method calls, etc.

@valpackett
Copy link
Contributor Author

Added newtypes for everything in connection. Absolutely hated this process, editing generated code is evil >_< but whatever, not my project haha.

Also the closures are typed now. name_lost has a nullable connection because it can be called when connecting to the bus failed: https://developer.gnome.org/gio/stable/gio-Owning-Bus-Names.html#g-bus-own-name

&mut error,
);
if error.is_null() {
Ok(RegistrationId(NonZeroU32::new_unchecked(id)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe safer to use `new(id).expect' ?

Copy link
Contributor Author

@valpackett valpackett Jun 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what is used in glib e.g. for SignalHandlerId

I don't think we really need to test gio's function contracts on every call :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glib checked it before use new_unchecked

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah either add an assertion before and new_unchecked(), or new() and expect(). glib didn't do the latter because in older Rust you don't get too useful source file / line number with expect().

@valpackett
Copy link
Contributor Author

And closures themselves are not optional, because you'd have to provide a type argument anyway..

@sdroege
Copy link
Member

sdroege commented Jun 4, 2020

Added newtypes for everything in connection. Absolutely hated this process, editing generated code is evil >_< but whatever, not my project haha.

Yeah it sucks but I'm not sure what the alternative would be other than keeping the API suboptimal. The goal is not to keep the amount of work we have to do low :) There are unfortunately various patterns that we can't detect automatically.

I'll go through the whole code again later today but I guess this is basically read now :)

Gir.toml Show resolved Hide resolved
src/dbus.rs Show resolved Hide resolved
src/dbus.rs Outdated Show resolved Hide resolved
src/dbus.rs Outdated Show resolved Hide resolved
Copy link
Member

@sdroege sdroege left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from that, good to be merged from my side.

@valpackett
Copy link
Contributor Author

Done.

I'm not sure what the alternative would be

Adding more and more features to Gir.toml all the time? ;)

Copy link
Member

@sdroege sdroege left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good to me :) @GuillaumeGomez @EPashkin any more comments from you?

@EPashkin
Copy link
Member

EPashkin commented Jun 4, 2020

IMHO it looks good, Thanks, @myfreeweb

@sdroege
Copy link
Member

sdroege commented Jun 4, 2020

@myfreeweb Do you want to provide your example from the screenshot or something similar (like using the notification dbus interface) as an example to https:/gtk-rs/examples/ ?

@valpackett
Copy link
Contributor Author

Yes, sure. (How are versions handled? I see the examples repo doesn't use git versions of crates..)

@GuillaumeGomez
Copy link
Member

Look at the pending branch. ;)

@sdroege sdroege merged commit 47e70e4 into gtk-rs:master Jun 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants