D-Bus how to create and send a Dict?

I have a process that provides a DBus method with one of the arguments taking the following signature of type a{sv} :

Dict from {String, Variant}

The libDBus documentation for dbus_message_append_args does not provide enough help for this. Some information appears in the specification in type containers , in particular:

DICT_ENTRY works exactly like a structure, not parentheses, it uses curly braces, and it has more limitations. Limitations: this only happens as an array element type; it has exactly two single complete types inside curly braces; The first single full type ("key") should be the base type, not the container type. Implementations should not accept dict entries outside arrays, should not accept dict entries with zero, one or more fields, and should not accept dict entries with keys that do not contain a base type. A voice recorder is always a key-value pair.


When I try to add a dict, I get the following error message:

 type dict_entry isn't supported yet in dbus_message_append_args_valist 

Although I actually use dbus_message_append_args (I think the error message is somewhat disabled).

There are two other alternatives to dbus_message_append_args() :

dbus_message_iter_append_basic() as well as dbus_message_iter_append_fixed_array()

For now, I can create an empty Dict container with the following:

  const char * container_d_sig = "{sv}"; DBusMessageIter iter, sub; dbus_message_iter_init_append(msg, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, container_d_sig, &sub); dbus_message_iter_close_container(&iter, &sub); 

None of the append methods support adding a structure. Not sure what to try here ...

+5
source share
1 answer

Firstly, about D-Bus libraries: you talk about dbus-glib in several places, but the functions you are talking about are not part of dbus-glib, but libdbus. If you are still trying to find a better way to use D-Bus, I suggest you forget about all of these: libdbus is very low-level (the documentation even starts with "If you use this low-level API directly, signing up for some pain"), and dbus-glib is deprecated . The best D-Bus API currently is GDBus, which is part of the GLib GIO : it is a much better developed API than either of the other two, well tested and supported.

Now, regarding the actual question, the documentation for dbus_message_append_args() says this quite clearly:

To add basic types of variable length or any more complex value, you should use an iterator, not this function.

In other words, you should use dbus_message_iter_open_container() to prepare the iterator until it points somewhere where you can use dbus_message_iter_append_basic() . Note that in your example, the dictionary is a container, the dictionary entry is a container, and the option is a container ... In other words, it is quite complex pretty quickly. If you really want to do this, take a look, for example. Connman for examples.

As I mentioned, a sensible route is GDBus. There, creating even more complex signatures is quite simple, since you can use the GVariantBuilder API:

 GVariantBuilder builder; g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add (&builder, "{sv}", "name1", my_variant); /* Now use the builder results with g_dbus_connection_call() or g_dbus_proxy_call() */ 
+3
source

All Articles