Using Introspection to listen to a set of signals unknown at compile time [dbus-glib]

Ed Martin lists at edman007.com
Fri Oct 23 06:39:59 PDT 2009


Hi,
    Thanks for the help so far, but I still have a few more questions.

Simon McVittie wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> I hope your application is some sort of debugging tool; if it's not, please
> consider writing a well-defined D-Bus API in which signals and methods have
> known signatures (you can use the 'v' variant type, or maps from string to
> variant (i.e. a{sv}), to provide extension points). You'll find that all the
> major bindings work much better if you do that.
Could you explain this a bit more? What I want to do is write a plugin 
for http://ssl.bulix.org/projects/lcd4linux/ so this is not a debugging 
application, but what I want to do is fairly simple, just listen for 
signals as defined in a config file and use those as both triggers and 
input data (which basically means for a given signal the most complex 
part should be converting the arguments into strings). I realize that 
dbus would probably let complex types pass in the signals, but I'm don't 
think I really need to support that and can just skip all but the 
primitive types (not important for me). As I see it something like this 
should not need a complex setup and would not benefit from defining 
everything at compile time as that would severely limit what 
applications can be added by a user without really adding anything useful.

So how would I go about writing a "well-defined D-Bus API in which 
signals and methods have known signatures"? Are you suggesting I modify 
a binding to accomplish it? I will try using the low level dbus API and 
see what happens.
>
> If that's not possible, then you'll have to stop using dbus-glib, and use a
> lower-level API, like libdbus or the dbus.lowlevel part of dbus-python.
>
> On Thu, 22 Oct 2009 at 21:39:35 -0400, Ed Martin wrote:
>> Basically I want to write an application that can listen to signals 
>> determined at runtime (loaded from a config file). I was told that for 
>> an application written in C dbus-glib is the way to go (and it is going 
>> to stay in C because it will eventually become a plugin to a larger 
>> application written in C).
>
> dbus-glib is too simple for what you're trying to do; for this functionality
> you'll have to use libdbus directly (add a match rule, and add a filter
> function to look for the signals).
>
>>      Since I do not know the signals at compile time I can't know their 
>> types, that makes dbus_g_proxy_add_signal() completely useless. 
>> According to the docs, thats ok as long as the application supports 
>> introspection.
>
> That statement in the docs is not true. It's just as well, because if the docs
> were true, services could remotely segfault clients by changing their reply
> to Introspect().
>
>> dbus_g_proxy_connect_signal(sess_proxy, name, 
>> G_CALLBACK(lcd_sig_received), "lol", NULL);
>
> What parameters do you think lcd_sig_received would take? You don't know the
> type for dbus_g_proxy_add_signal, but neither do you know the type in order
> to write lcd_sig_received() with the correct signature.
I was hoping that the callback could somehow take a variable number of 
arguments with some method of determining the type of the arguments.
>
> For instance, if you assume that the signal has two uint32 parameters, you'd
> write:
>
> static void lcd_sig_received (DBusGProxy *sess_proxy, guint a, guint b,
>     gpointer user_data)
>
> but if the signal actually had one array of strings as its parameter, your
> callback would be called with parameters (DBusGProxy *sess_proxy,
> GStrv *strings, gpointer user_data2) placed on the stack.
>
> On a 32-bit platform (for example) you'd get a = GPOINTER_TO_UINT(strings),
> b = GPOINTER_TO_UINT(user_data2), and user_data undefined; a and b would be
> meaningless, and in any application where user_data is dereferenced by the
> callback (in practice you usually need to), doing so would crash you
> immediately.
>
> If you write a libdbus filter function, on the other hand, you'll receive a
> pointer to a DBusMessage object, which is self-describing (admittedly with a
> particularly annoying API); your filter function can do the recursive
> unmarshalling itself, in as elaborate a way as you want.
>
>> I know of 
>> many applications using many different bindings that are able to read 
>> signals unknown at compile time (like dbus-monitor and d-feet).
>
> Yes, but neither of those uses dbus-glib...
>
> dbus-monitor uses libdbus, and unmarshals each message (to turn it into
> text) on-demand.
>
> d-feet uses libdbus via (the low-level part of) dbus-python; dbus-python only
> uses dbus-glib for main loop integration.
>
> Regards,
>     Simon
> -----BEGIN PGP SIGNATURE-----
>
> iQIVAwUBSuGZVE3o/ypjx8yQAQhYOxAAjeA2XkdXWLWyv1OfZUxwx/RcDiXornhG
> 8iu7zckqHczHssjKLOyzf2JuMO8L6Htmzm7yaOyN0VG2ZS0ugryZzIGo5Hl19g/i
> UkZ94XnMexpLB+Z0BRwVCchDWYnKdfaiEEJ/UVxDBPighSo7ujsf/S72SnaK+osF
> Esb2gfDI/VADvqQ0v1V+9rVDf7ChoJlnw5ce6k3o28HUXUSeAa3Lz1wA5OBg4juB
> FjVGj11msVZstZXWAgQggN22Nt5eYZpD3TUKZ6FDoPHR13uRNd5IH8Jah/F1amNh
> PK6QxIM5tO+sPCF01s+FUBDVPKPBEamX+TD8CQpfOwOPQPGnms90KpMXyueefVNy
> uNRnkR0WnLhqEHRdRhBbFHPUNfm+30ycwMI1R1VqjldFFb5NBa8WV/z5yO8T693a
> It/nRn+VXCTTBQJ8MlguMS5ArVo7MsHDWXDCdcEVJSgB3cigx3nTqC2zgypJDqe4
> 10twFZBryJLVSWDdGM3sGvg/UDL+lEH1U+3t02glqUDBuqfWOAJKtyAbGdWxEV7v
> frgK0+Ekjzv/LVigiBHXWSFwvoBRo7wdqil3M/XrpkpMFtOEotFxpLqZwsyJibVK
> yN8jW2bomrUo3049Ckr3CEkThYfNnMJzGNn2Ci6S8ubhpS/egHB/JNn5c1pFRRTW
> 0gvfDh2/7Jc=
> =27SJ
> -----END PGP SIGNATURE-----
> _______________________________________________
> dbus mailing list
> dbus at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dbus



More information about the dbus mailing list