glib dbus bindings notes

David Zeuthen david at fubar.dk
Tue Mar 3 10:19:25 PST 2009


Hey, 

thanks for taking a look.

On Tue, 2009-02-24 at 21:03 -0500, Havoc Pennington wrote:
> Hi,
> 
> Finally, maybe it's useful to go more concrete looking at eggdbus and
> mentioning some of the specific stuff in there. I know it's a lot of
> comments but I'm just giving my opinion, take it for whatever it's
> worth.

First some history: EggDBus was written with the express purpose of
having a good C/GObject binding for D-Bus simply because I was tired of
writing the same code over and over again and cutting corners because
getting some things right with libdbus is way too much effort. 

I also liked the clean async style that Alex introduced in GIO and it
seemed like a good fit for a D-Bus binding for C/GObject. Especially if
we introduce stuff like GFiber in the future.

And, FWIW, I'm pretty happy with the way C/GObject binding turned out
(am using it in a couple of places already); I think that most of your
concerns are about the low-level bits; is that about right?

So, anyway, to cut a long story short, EggDBus never really was written
with language bindings in mind. It was also written over a period of
only 5-6 weeks so I never really had time to worry about all that jazz.
I just wanted the C/GObject stuff sorted so I could get on with my life
and write my apps. That's also why some of the API (like BusNameTracker
and Connection) is still incomplete; I just needed enough to get the
object mapping working in C.

So I don't really know about bindings. I kind of assumed most other
languages had their own bindings in place based on libdbus since that's
pretty much what libdbus is all about.

So that's the history. On to your suggestions. 

First, I agree that it's important to be bindings friendly, especially
with things like GObject introspection. I also agree that the ideal case
is to having a native object mapping for each language (the other
possibility, in lieu of a native object mapping, is to bind the
generated C/GObject proxies. Not 100% nice, there's the performance
penalty and so on but it would basically work.).


> * Maybe this should have some use of gobject-introspection. In
> particular I think it might be nice if I have any introspectable
> object, to be able to just stick it on the bus, and have incoming
> calls mapped to it. Then I can just write a normal gobject, stick it
> on the bus, and have it work, much of the time. In fact for
> *implementing* objects I'm not sure there's much point in generating
> anything statically beyond the g-i typelib ... a couple
> gobject-introspection annotations could specify that some char* are
> really object paths, or whatever.

When implementing objects to be exported on the bus you typically want
an async way of returning and you also (in the case of system daemons)
want to know about the other end for authorization decisions. So I'm not
really sure how well this would work. I don't know, maybe it would work
great. 

I'm sorta biased here since I mostly do system bus services where it's
really important to check for authorizations and stuff like that.

Anyway, I agree it should be possible to at least do this whether it's a
good idea or not. And FWIW it's entirely possible to do this with
EggDBus today; just create a proxy class and implement the vfuncs in
EggDBusInterface.

>  * object proxy and interface registration is part of object mapping;
> should really be split out

I'm not sure I like that. I think it would be useful only having to deal
with a single object (the connection) and use that for most of the
things.

I can see where you are coming from though; you don't want
get_proxy()/register_object() in bound versions of EggDBusConnection
because these are only useful in C, right?

So I think maybe we want

 GBusLowlevelConnection

that is useful for all languages and then

 GBusConnection

for the C/GObject binding. But that's ugly. Ideas?

>  * egg_dbus_connection_get_bus() is blocking rather than async; 

Actually get_bus() is not blocking; it's just like other proxies;
getting a proxy in EggDBus never ever blocks. And IMO it shouldn't.

> imo
> apps should never get the bus anyway, they should always instead
> either ask to acquire a name or ask to watch a name, and the bus
> connection is dealt with behind scenes

Often you want to call other methods on the bus because you need
something like that, e.g. get_connection_unix_user() and so on.

Anyway, the way it works right now is that the EggDBusBus interface

http://people.freedesktop.org/~david/eggdbus-HEAD/eggdbus-eggdbusbus.html

is generated just like other proxies. And the way you take names on the
bus is simply by using the generated proxy. In practice this works
really well.

I guess your suggestion really is that EggDBusBus should be written by
hand so we can put some extra client-side business logic into it; e.g.
points 3. and 4; single instance, --replace support, all that jazz. And
also make sure it can be bound to other languages like C without looking
weird.

That might not be a bad idea; we could do things like caching the unix
users and selinux security contexts. I guess I'm fine with that.

>  * egg_dbus_connection_send_message_with_reply_sync(): imo it's worth
> strongly considering flat-out disallowing synchronous calls. Yes async
> is painful in C. No you should not block in a GUI app or a daemon,
> which means almost all apps. Remove the temptation!

The only class of apps where IMO sync calls are OK (besides from
threads) are in command line apps where the user knows what he is doing
and he can do ctrl+c (and even for some things in commandline apps it's
still not OK). I thought about guarding sync calls behind a

 EGG_DBUS_ALLOW_SYNC_CALLS_YES_I_KNOW_WHAT_I_AM_DOING

macro or something. I don't know. I just don't think it's realistic to
remove sync calls, by the same token, should we remove all the sync
calls in GIO? I don't think so.

>  * EGG_DBUS_CALL_FLAGS_BLOCK_IN_MAINLOOP nooooooooooooooooooo!

Yeah, I really should remove that.

Regarding your other comments, I largely agree with them and this mail
would be too long if I replied to all of them.

So, to sum up, the main suggestions you are making are

 - Rework low-level bits of EggDBus so it's like dbus-hippo-helper

 - Don't try to hide libdbus in the low-level bits
   (but do hide it from the high-level bits)

 - make sure the all gunk needed for the C/GObject binding is separate
   from the low-level stuff (a separate library even?)

Is that about right?

I guess I'm fine with doing this; after all, the C/GObject binding is
the bulk of the code.

     David




More information about the dbus mailing list