dbus_message_set/get_data usage

Simon McVittie simon.mcvittie at collabora.co.uk
Thu Dec 12 03:17:32 PST 2013

On 12/12/13 08:07, Brosseau, Vincent wrote:
> Now I understand that I can't attach data to the message in this way... But I'm
> not sure to understand what are dbus_message_set/get_data used for,
> exactly (your example with Python doesn't help me, sorry)...

If you don't know why you'd need them, then you don't need them; they're
for unusual situations which tend to appear when writing high-level
language bindings. They're analogous to g_object_(get|set)_data(), if
that's any help.

If in doubt, prefer to use a high-level D-Bus library like GDBus (C,
GLib/GObject, reimplements libdbus, my preferred choice) or QtDBus (C++,
Qt, wraps libdbus) rather than using libdbus directly. The libdbus
documentation does say "If you use this low-level API directly, you're
signing up for some pain".

> Anyway, I have another question about attaching parameters.
> When I use dbus_message_iter_init_append() and then dbus_message_iter_append_basic(),
> the latter needs a (void *)parameter as the third argument.

Yes, or more precisely, a pointer to a type chosen to be appropriate for
the second argument: for instance, DBUS_TYPE_INT32 -> (dbus_int32_t *),
DBUS_TYPE_STRING -> (char **).

> 	// param contains a field with the number of string values to attach => count
> 	// and an array of string values => value[MAX_COUNT]

Please be specific: if in doubt, quote actual code. Does it look like this

    struct {
      int count;
      char *value[MAX_COUNT];   // of which 0..count-1 contain values
    } param;

    param.count = 2;
    param.value[0] = strdup ("hello");
    param.value[1] = strdup ("world");

or more like this?

    struct {
      int count;
      char value[VALUE_LEN][MAX_COUNT];
    } param;

    param.count = 2;
    strncpy (param.value[0], "hello", VALUE_LEN);
    strncpy (param.value[1], "world", VALUE_LEN);

> 	for( int a = 0; a < param.count; a++ )
> 	{
> 		dbus_message_iter_append_basic( &dbusArg, DBUS_TYPE_STRING, &param.value[a] );

If the type of value is char *[n] then that should work, AFAICS:
value[a] is a char * pointing to the "h" of "hello", so &value[a] is a
char ** pointing to a char * pointing to the "h" of "hello", as required.

If the type of value is char[m][n] then value[a] is a char[m] containing
"hello", &value[a] points to the "h" of "hello", and your app crashes
when libdbus treats it as a char **, and as a result, tries to
dereference the bytes at and after the "h" as a char *.

With hindsight, either the type of the third argument should have been
const DBusBasicValue * to force the use of a suitable temporary
variable, or there should have been a family of type-safe functions like

> 		const char *arg = param.value[a];
> 		dbus_message_iter_append_basic( &dbusArg, DBUS_TYPE_STRING, &arg );

If in doubt, use a temporary like this, or (preferably) use a
higher-level D-Bus library. I use GDBus, when I can.


More information about the dbus mailing list