I've recently been learning about libdbus
by writing a simple tool that sends mpris messages to active media players.
The first step of this has been fetch a list of media players via DBus:
// send the ListNames command over the DBus
DBusMessage* msg = dbus_message_new_method_call(
"org.freedesktop.DBus",
"/",
"org.freedesktop.DBus",
"ListNames");
// send the message
DBusPendingCall* call;
dbus_bool_t success = dbus_connection_send_with_reply(con, msg, &call, 100);
if (!success || call == NULL) return 1;
// wait for a reply
dbus_pending_call_block(call);
// check reply
DBusMessage* reply = dbus_pending_call_steal_reply(call);
I must now parse the DBus reply for a list of media player names. After reading the reference material, I believe this should be possible via dbus_message_get_args, as the documentation notes:
arrays of string, object path, and signature are supported; but these are returned as allocated memory and must be freed with dbus_free_string_array(). [...] To get a string array pass in "char ***array_location" and "int *n_elements".
This led me to write the following:
// pull list of players from reply
const int MAX_ARGS = 10;
const char** args;
dbus_message_get_args(reply, &err, DBUS_TYPE_ARRAY, &args, &MAX_ARGS);
But upon checking my DBusError, I get the following message:
DBus Error: org.freedesktop.DBus.Error.InvalidArgs Argument 0 is specified to be an array of "unknown", but is actually an array of "string"
I originally assumed I must have been passing a bad DBUS_TYPE
but couldnt find one more suitable than DBUS_TYPE_ARRAY
.
I'm aware that this is also possible by using a dbus_message_iter
call but the documentation seems to suggest this is not necessary, and even suggests using get_message_args
where possible.
So the actual question is... am I missing something about the documentation, or calling the function wrong? Or is getting a list of strings actually not possible with this method?
I would suggest reading the libdbus source code to be sure, but something like this is my recollection:
dbus_message_get_args(reply, &err, DBUS_TYPE_ARRAY,
DBUS_TYPE_STRING, &args, &len, DBUS_TYPE_INVALID);
Note that len
is not a maximum length you can specify: libdbus will write the actual length of the array there. I'm not 100% sure of the argument order here, you might have to read the source to be sure.
If you are now thinking "but that would be a weird API with bad documentation"... you would be right: As Philip mentioned using libdbus is not a good choice to make in 2020.