DBus and Qt programming

For the past few days I’ve been trying to get more complex data sent via DBus. As one would say here in Ireland:

Je’zus H. Christ

Playing with python was easy. There are lots of examples on communicating complex data structures. But with Qt… It’s a bit more complex, because there are only a set of simple examples.

To keep things simple, I chose the car example:

  • The car/ is the “server”. It receives the request from the client and sends a reply.
  • The controller/ is the “client”. It “calls” a method on the server, gets the results and processes them

Notice the extra method called structer with two outputs:

  • a structure MyStruct
  • a qlonglong

For the purpose of this test, MyStruct is a simple structure:

The client calls structer. The server updates the qlonglong and the MyStruct object and sends them back to the client to be used.

h2. The D-Bus translation

First, note the “arg0” annotation, required for the struct type:

This actually helps the qdbusxml2cpp to typ-ify the generated code.

On the client (controller) part, we use the following command:

On the server (car) part, use the command:

for the same “car.xml” file.

The XML resulted from the introspection description for structer is translated by the Qt into:

aka first "out" argument is passed as the return argument for the function. The other arguments are passes as function arguments. It's good to know this, because you can implement your own method without looking at the *_p.h files for guidance.

... but not yet.

h2. The Server Side

First issue is that qdbusxml2cpp is not smart enough to implement custom marshaling. It offers instead a guideline for us:

once we change the commented line to something like:

we’re good to go. The line

MyStruct s = static_cast(parent())->structer(out1);

implies that the parent() object is a pointer to Car, which, in turn contains a structer() implementation. You can change the call into whatever code capable of updating the out1 parameter and returning a MyStruct struct.

For the purpose of this exercise, we implement a structer() method in our car.cpp like so:

and include the “car.h” in.

The downfall of this server approach is that it requires manual adjustment of a generated file. So, once you have the .cpp and the _p.h files available, save them to your repository. Have them regenerated only if needed. Note that trolltech’s Qt tarball contains already generated files, instead of scripting 🙂

h2. The Client Side

Here the fun begins! First, open the .ui file and add a new button to call the structer(). In controller.h complete the on_XXXX_clicked() with the new button ID (let’s call it on_structer clicked())

The implementation follows the D-Bus guidelines from the other buttons:

The result is that every time you press the button, it’s going to call the server (car) and get the MyStruct structure from the server.

… but not yet! 🙂

h2. The Glue

D-Bus is a relatively simple mechanism and supports a predefined list of types. Composite types are sent as structures and have to have custom marshaling implemented. This is done via < </>> C++ operators.

Once you have the structure defined, the Qt way is a three-step process.

h3. Declare the Metatype
Place the line

somewhere outside body/class/namespace blocks. I’ve put it in mystruct.h after the struct declaration.

h3. Declare/Implement the Marshaller

This actually means you need to declare/implement the < </>> operators. For convenience, I’ve declared them in mystruct.h as well and implemented them in mystruct.cpp like this:

h4. mystruct.h

h4. mystruct.cpp

h3. Register the Type with D-Bus

Once you have done the above steps, everything is almost ready. Now you only need to add the type to the list of custom marshalers with qDBusRegisterMetaType.

In mystruct.h, add:

and have it called in both the client and server, somewhere before the actual D-Bus methods are called (e.g. in main() or in some constructor).

Look at the attached example for details.

Good luck at hacking your own D-Bus stuff!

9 thoughts on “DBus and Qt programming

  1. I greatly appreciate your post !!!
    It was very very helpful.

    With our (latest 4.3) QT release Q_CREATE_METATYPE
    I had to replace with Q_DECLARE_METATYPE and, BTW,
    qdbusxml2cpp is doing better job now – no need in manual modifications of the generated files.

    Thanks again !

  2. Where do I find “the attached example”.

    I’m new to QtDbus and it all seems like BFM to me. Poorly documented and hard to understand.

    It looks like your example is the only place I’ve seen an example of passing a structure…

  3. Thank you very much for your post. I am working on an issue and still solved.

    Is there any detailed manual about complex data sending via DBus using Qt? annotations ect.

  4. @Scott: The attached example is a valid link (sorry, but the new theme painted the links the same colour as the normal text)

  5. @Emre: I’m not aware of any “manual” or detailed information about that. I ran across the problem myself and the above is the solution I came up with.

  6. Do you have any example with complex types like “a{ss}”, An array of dictionlay.?

    • Unfortunately I haven’t had the chance to touch qtdbus since. I think though that you should be able to serialise them implicitly (provided that all components can be serialised).

Comments are closed.