Details
-
Bug
-
Resolution: Incomplete
-
Not Evaluated
-
None
-
4.7.3
-
None
Description
In qdbusviewer, if you try to call methods with more complex signatures, it either silently fails or you get the error "Unable to find method <method name> on path <path name> in <interface name>" in a popup box.
Example: On a contemporary linux box with HAL installed, try calling the following methods on the system bus:
- "GetAllDevices" on org.freedesktop.hal, path org/freedesktop/Hal/Manager, interface org.freedesktop.Hal.Manager
Signature in: ""
Signature out: "ao" (Array of object paths)
Result: A list is returned and displayed in the lower log window.
- "GetAllDevicesWithProperties", same name, path and interface
Signature in: ""
Signature out: "a(oa {sv})" (array of a compound type)
Result: Dialog box "Unable to find method GetAllDevicesWithProperties on path /org/freedesktop/Hal/Manager in interface org.freedesktop.Hal.Manager"
In contrast to the second call, executing the low level command line tool
"dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freedesktop/Hal/Manager org.freedesktop.Hal.Manager.GetAllDevicesWithProperties"
works like a charm (proper data structures returned).
I read the sources and traced this situation back to src/dbus/qdbusmetatype.cpp:301, function QDBusMetaType::signatureToType(const char*). In it, the first character of the argument is parsed and (in a switch construct) checked for basic types. The last type however is DBUS_TYPE_ARRAY (line 438). If it is encountered, the second character is parsed and checked only for a few simple types (DBUS_TYPE_
{BYTE,STRING,VARIANT,OBJECT_PATH,SIGNATURE}), otherwise QVariant::Invalid is returned, which in the end leads to qdbusviewer not finding the method:
1. call method in the UI
2. QDBusViewer::callMethod(const BusSignature&) is executed, which creates a new QDBusInterface based on service, path and interface of the method
3. To get the available methods, in the end QDBusMetaObjectGenerator::parseMethods() is called by the constructor
4. This method calls QDBusMetaObjectGenerator::findType() with the signature of each method contained in the introspect XML data
5. From there, the above mentioned QDBusMetaType::signatureToType() is called and returns the type.
6. parseMethods() checks the type and discards methods where the in/out type is QVariant::Invalid; other methods (with "valid" signatures) are added to its methods list
7. QDBusViewer::callMethod(const BusSignature&) retrieves the interface's QMetaObject and iterates over the methods list using QMetaObject::method(int). In there, it only finds the methods which were added in the step before.
I'd expect a generic D-Bus interface to be able to handle not just a few select compound types. Is this behaviour by design, i.e. is qdbusviewer intended as a quick hack for demonstration purposes, or should this be fixed?
If you need more info I'd be happy to provide it.