Re: GLib plans for the next cycle



On Fri, 2009-04-03 at 19:56 +0100, Will Thompson wrote:
> I don't think that relying on having correct introspection data to
> marshall messages is a sound idea for a DBus binding. The C
> representation of an 'a{uas}' where the values are all the empty list
> should contain all the information you need to determine its D-Bus type.
> It sounds like with EggDBus that's not possible without you discovering
> the type by external means. If the C-side type system isn't powerful
> enough to express the D-Bus-side types (which GType isn't), then the
> C-side type system should be improved. Gluing the D-Bus type onto the
> side doesn't sound like a clean way to do this to me.

Keep in mind that the goal of EggDBus was just to provide an object
mapping using generated code. With generated code it is a non-issue
whether you have to pass just a GType or the pair (GType, D-Bus
signature) since all that happens from generated code.

Of course this approach is not very clean if your goal is to also
provide some a C API that is useful outside the context of generated
code. While I don't think that's compelling (you are going to lose type
safety for starters) apparently a lot of people want this kind of API. I
agree it's sensible to have.

> Apparently, back when Telepathy was started, dbus-glib used to have a
> similar problem with collections containing structs. It relied on
> inspecting the contents of a GValueArray to determine the type of the
> struct it represents, which obviously can't work for a(ss) since the
> array might be empty. (Rob Taylor fixed this by adding a parameterized
> struct type.) More recently, Rob McQueen had to fix dbus-glib to allow
> complex types in maps. If the binding gets the type system right and
> complete from the start, problems like this (and the current situation
> where dbus-glib can't send 16-bit ints, causing interoperability
> problems with bindings which expect them) won't arise later.

Yes, we probably want a type system where you can do e.g.

g_bus_send_message (connection,
                    "org.foo.SomeService",
                    "/org/foo/SomeObject",
                    "org.foo.SomeInterface.SomeMethod",
                    cancellable,
                    async_ready_callback,
                    G_TYPE_PTR_ARRAY (G_TYPE_PTR_ARRAY (G_TYPE_STRING)),
                    array_of_array_of_strings,
                    G_TYPE_HASH_TABLE (G_TYPE_STRING,
                                      G_TYPE_PTR_ARRAY (G_TYPE_STRING)),
                    hash_of_strings_to_ptr_array_of_strings,
                    G_TYPE_INVALID);

instead of

g_bus_send_message (connection,
                    "org.foo.SomeService",
                    "/org/foo/SomeObject",
                    "org.foo.SomeInterface.SomeMethod",
                    cancellable,
                    async_ready_callback,
                    G_TYPE_PTR_ARRAY, "aas",
                    array_of_array_of_strings,
                    G_TYPE_HASH_TABLE, "a{sas}",
                    hash_of_strings_to_ptr_array_of_strings,
                    G_TYPE_INVALID);

e.g. enable the API user to express a complete D-Bus signature via GType
instead of having to pass both the GType and the D-Bus signature.  That
is essentially what you are talking about right?

Personally I don't think it's a big deal having to do the latter. In my
view both of these approaches are much worse than having a generated
GInterface for the org.foo.SomeInterface D-Bus interface and having
GObject-derived classes for the structs you need. YMMV though.

> > The point is that you can always get to the D-Bus signature and from
> > that you can infer the complete type.
> 
> dbus-python has shown that that's not true. When marshalling a dict (for
> instance), it has to guess what the type is, and it sometimes guesses
> wrongly, leading to hard-to-debug problems. It tries to quietly
> introspect behind your back to work around this, and that too causes
> problems.

Certainly if you pass your low-level code the D-Bus signature for a
single complete type (like the above example and like EggDBus does) no
guessing is _ever_ needed. I mean, the D-Bus signature _defines_ exactly
what to output so if you run into problems (e.g. with Python) maybe it's
because you have a problem decoding the native types the user passed in
(which sounds easy to run into with Python).

> > The set of distinct D-Bus signatures you encounter in a app where you
> > would need to do this (e.g. no need to do this for primitive types) is
> > most likely bounded to a couple of dozen types at the most (unless you
> > are some odd-ball corner case like a D-Bus version of gconf-editor) so I
> > don't think this is a big deal at all.
> 
> I think regarding types more complicated than 'as', 'b', 'i' etc. as
> "odd-ball corner cases" is a mistake, 

I think you misunderstood what I meant with odd-ball cases here. What I
meant was with a D-Bus-ified version gconf-editor being an oddball case
was simply ... that it would run into a lot of distinct types assuming
we'd store arbitrary variants in GConf. So a lot of types would be
registered with the G type system.

> particularly when talking about
> one of the core components of the GNOME platform. The fact that D-Bus
> has an expressive recursive type system is good, since it means you can
> model interesting concepts without forcing them into an incorrect
> representation. But for this to be useful, the binding has to support
> complex types just as much, if not more, than simple ones, particularly
> in a language like C.
> 
> Telepathy uses some pretty complex D-Bus types; an example that comes to
> mind is 'a{ua(a{sv}as)}'. If working with this type in the standard GLib
> D-Bus binding is no less painful than it currently is with dbus-glib,
> then using a component of the GNOME stack with a standard GNOME binding
> will be unnecessarily difficult. I really don't want to end up in a
> situation where I have to use an external library instead of the one
> inside GLib to make working with Telepathy less painful.

The key to dealing with signatures like a{ua(a{sv}as)} is to have good
native type-system support for it. In C with GObject I'm fairly
convinced that unless you generated an easy to use GObject class per
struct type you are somewhat doomed (that's my experience with dbus-glib
anyway).

FWIW, with the object mapping I have in EggDBus (and what I essentially
propose for GLib) dealing with methods with signature a{ua(a{sv}as)} in
C and GObject isn't painful at all. You'd get a generated GObject class
for the (a{sv}as) structure (with a constructor and getters/setters for
the two elements) and the rest are just dealing hash tables and pointer
arrays. Piece of cake really.
 
Btw, if you examine the EggDBus source code you will find that the
test-cases covers even more interesting and bizarre signatures e.g.

http://cgit.freedesktop.org/~david/eggdbus/tree/src/tests/com.example.Frob.xml

and all these work fine. A goal of the EggDBus object mapping was in
fact to cover every really bizarre corner cases hence the test suite
being full of bizarre stuff like this

<method name="TestHashTableOfHashTablesOfStructures">
 <arg direction="in"  type="a{sa{s(ii)}}" name="hash_of_hash_of_points">

and dealing with that isn't at all unreasonable.

     David




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]