7

While using the qdbusxml2cpp program to convert the following xml to a Qt Class, I am getting this error:

qdbusxml2cpp -c ObjectManager -a ObjectManager:ObjectManager.cpp xml/object_manager.xml 
Got unknown type `a{oa{sa{sv}}}'
You should add <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="<type>"/> to the XML description

D-Feet description:

enter image description here

XML:

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node><interface name="org.freedesktop.DBus.Introspectable"><method name="Introspect"><arg name="xml" type="s" direction="out"/>
</method></interface><interface name="org.freedesktop.DBus.ObjectManager"><method name="GetManagedObjects"><arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
</method><signal name="InterfacesAdded"><arg name="object" type="o"/>
<arg name="interfaces" type="a{sa{sv}}"/>
</signal>
<signal name="InterfacesRemoved"><arg name="object" type="o"/>
<arg name="interfaces" type="as"/>
</signal>
</interface><node name="org"/></node>

From this website ( http://techbase.kde.org/Development/Tutorials/D-Bus/CustomTypes ) I understand that I need to add an annotation to the XML for the tool to work properly.

Here is what I have so far:

a{oa{sa{sv}}}

https://alteeve.ca/w/List_of_DBus_data_types
o == A UTF-8 string whose value is a valid DBus object path.

array { object_path array { string array { string variant } } }

<arg name="customdata" type="a{sv}" direction="in" />
QVariantMap in the arguments (type "a{sv}")
QMap<QString, QVariant>

However, I'm not sure what the annotation should be for a{oa{sa{sv}}}, can someone please help me understand? Thanks!

PhilBot
  • 748
  • 18
  • 85
  • 173

2 Answers2

11

openSUSE imagewriter is a GPL licensed project which contains an example of how to do this.
(Relevant files: udisks2_interface.*)


a{sv} is a dict of string:variant pairs.
QVariantMap would fit this signature.

a{sa{sv}} is a dict of string:a{sv} pairs.
QMap<QString, QVariantMap> would fit this signature.

a{oa{sa{sv}}} is a dict of objectpath:a{sa{sv}} pairs.
QMap<QDBusObjectPath, QMap<QString, QVariantMap>> would fit this signature.

We should hide those angle-brackets behind some typedefs in a header file:

typedef QMap<QString, QVariantMap> InterfaceList;
typedef QMap<QDBusObjectPath, InterfaceList> ManagedObjectList;

Then declare their QMetaTypes in the same header file:

Q_DECLARE_METATYPE(InterfaceList)
Q_DECLARE_METATYPE(ManagedObjectList)

Then register them with the Qt metatype system at runtime:

qDBusRegisterMetaType<InterfaceList>();
qDBusRegisterMetaType<ManagedObjectList>();

Then we can annotate the XML:

<method name="GetManagedObjects">
  <arg type="a{oa{sa{sv}}}" name="objects" direction="out" />
  <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="ManagedObjectList"/>
</method>
<signal name="InterfacesAdded">
  <arg type="o" name="object"/>
  <arg type="a{sa{sv}}" name="interfaces" />
  <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="InterfaceList"/>
</signal>
Oktalist
  • 14,336
  • 3
  • 43
  • 63
  • Given annotation syntax didn't work for me (Qt 5.9.2). I've got same error from qdbusxml2cpp as author of question did. – Artem Pisarenko Jan 22 '18 at 12:14
  • 1
    _(Ok, since my attempt to fix answer was rejected and I don't want to post whole new answer intended just to fix this small issue with this full and perfect answer, I have to write fix here, in comment, where I can't format code properly.)_ Required modification of XML syntax: each `annotation` tag should be taken out from `arg` tag and placed separately just after it. **Example:** **instead of** [](http://dummy.url) – Artem Pisarenko Jan 22 '18 at 18:38
  • @ArtemPisarenko Your edit looks good so I've approved it, thanks. – Oktalist Aug 12 '21 at 11:59
1

I had the same problem with the newer version (Qt5.12). I didn't want to modify the code generated, and found out how to generate this code properly.
qdbusxml2cpp wasn't sure how to deal with dictionary signatures. My solution is to add the annotations directly with the Qt types. as in this, for
"a{oa{sa{sv}}}" -> QMap<QDBusObjectPath, QMap<QString, QVariantMap> >

<method name="GetManagedObjects">
  <arg type="a{oa{sa{sv}}}" name="object_paths_interfaces_and_properties" direction="out"/>
  <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QMap&lt;QDBusObjectPath,QMap&lt;QString,QVariantMap&gt;&gt;"/>
</method>

With &lt fot < and &gt fot > . Then the code generated is correct.

Hope this will help someone, one day... after 8 years

Michael Haephrati
  • 3,660
  • 1
  • 33
  • 56