Categories

Meta

DBus tutorial, part 3

In the previous post we have seen how to call a simple method in a DBus exposed object. In this post we will talk about data-types and about properties.

In the examples that we have seen we talked only about strings but DBus has many datatypes, and they can be basic types and container types.The basic types are:

byte (type y);

boolean (type b);

int/uint 16/32 bit (type n,q,i,u);

double (type d);

unix_fd (type h);

string (type s);

object_path (type o);

signature (type g).

As you have seen every basic type is identified by a type character. This type character is used in the signatures of the methods and of the methods arguments and of the result type. Now we will see the container types:

struct (type ([field types]), ad ex. a struct composed of two fields, a string and an integer, has type (sn));

So, with the exception of the variant type, every container type has a signature composed of two or more characters.
The variant type is strange indeed, because it can represent every valid DBus type and the message will contain the signature of the actual passed value. The variant type is really useful because it enables DBus to manage properties. Here it is the d-feet representation of the org.freedesktop.DBus.Properties interface:

As you see the Get method has the signature:

Get: (String interface, String propname) -> (Variant value)

How could you express the signature of the Get method if you wouldn’t have the Variant type?
As you can imagine the Get method let’s you get the value of a property, the GetAll method let’s you get the value of all the properties and the Set method let’s you set the value of a property. Every method takes as argument the name of the interface so a property can be in more than two interface without misunderstandings.

Ok. Enough talk. Let’s see some code.

I want to write a simple battery monitor and I want to use the UPower daemon for that. UPower exposes an object for every battery in our computer and I want to use the object at path /org/freedesktop/UPower/devices/battery_BAT1.

To get the current battery level we want to read the Energy property of the and the EnergyFull as exposed by UPower at the object /org/freedesktop/UPower/devices/battery_BAT1 then we display the battery level percentage. The code gets interesting in the get_double_property:

As you see extracting a property value means calling the Get method of the org.freedesktop.DBus.Properties interface. The value is then extracted from the DBus response with the extract_double_from_variant function. The create_property_get_message just creates a plain DBus method calling message:

Here we see a new DBus library type: the DBusMessageIter. This type let’s you explore the data attached to a DBus message.

When you initialize an iterator with the dbus_message_iter_init call the iterator is placed on the first element. You can iterate to the next element with dbus_message_iter_next or check with dbus_message_iter_has_next if the iterator has a next element.

You can only extract values for the basic types using the dbus_message_iter_get_basic call. When you need to read a container type, such as our variant type, you need to initialize a sub-iterator with the dbus_message_iter_recurse call. Iterators are stack-only structures and must not be deallocated.

Now you can work with container types. In the next post we will talk about DBus introspection.