[PyQt] How to expose function accepting array of struct to D-Bus?
Evade Flow
evadeflow at gmail.com
Mon Aug 6 18:59:08 BST 2012
On Mon, Aug 6, 2012 at 1:03 PM, Phil Thompson
<phil at riverbankcomputing.com> wrote:
> On Mon, 6 Aug 2012 12:49:21 -0400, Evade Flow <evadeflow at gmail.com> wrote:
>> On Mon, Aug 6, 2012 at 12:29 PM, Phil Thompson
>> <phil at riverbankcomputing.com> wrote:
>>> On Mon, 6 Aug 2012 12:15:44 -0400, Evade Flow <evadeflow at gmail.com>
>>> wrote:
>>>> I'm trying to write a PyQt4-based mock object for a C++ app exposed
> over
>>>> D-Bus with the following interface:
>>>>
>>>> Q_CLASSINFO("D-Bus Interface", "com.acme.Audio.Control")
>>>> Q_CLASSINFO("D-Bus Introspection",
>>>> ' <interface name="com.acme.Audio.Control">\n'
>>>> ' <method name="echo">\n'
>>>> ' <arg direction="in" type="s" name="phrase"/>\n'
>>>> ' <arg direction="out" type="s" name="echoed"/>\n'
>>>> ' </method>\n'
>>>> ' <method name="setParams">\n'
>>>> ' <arg direction="out" type="(i)" name="error"/>\n'
>>>> ' <arg direction="in" type="a(iiiii)"
>>>> name="audioSourceParameter"/>\n'
>>>> ' <annotation value="QVector<AudioSourceParameters>"
>>>> name="com.trolltech.QtDBus.QtTypeName.In0"/>\n'
>>>> ' <annotation value="Errors::ErrorCode"
>>>> name="com.trolltech.QtDBus.QtTypeName.Out0"/>\n'
>>>> ' </method>\n'
>>>> ' </interface>\n')
>>>>
>>>> It's unclear to me how how the setParams() function should be
> decorated.
>>>> For the echo() function, I have:
>>>>
>>>> @pyqtSlot(str, result=str)
>>>> def echo(self, phrase):
>>>> return self.parent().echo(phrase)
>>>>
>>>> But what should I put for setParams()? I was tempted to write:
>>>>
>>>> @pyqtSlot('a(iiiii)', result='(i)')
>>>> def setParams(self, volume):
>>>> return self.parent().echo(phrase)
>>>>
>>>> But this results in:
>>>>
>>>> TypeError: C++ type 'a(iiiii)' is not supported as a pyqtSlot type
>>>> argument type
>>>>
>>>> So... how does one expose a function to D-Bus that accepts an array of
>>>> structs, each containing 5 ints?
>>>
>>> What would be the C++ signature? Try that as a string.
>>>
>>> Phil
>>
>> The C++ signature is:
>>
>> void setParams(QList<AudioSourceParameters> audioSourceParameters,
>> Errors::ErrorCode &error);
>>
>> where AudioSourceParameters is defined as:
>>
>> struct AudioSourceParameters
>> {
>> int volume;
>> int balance;
>> int fader;
>> int fadein;
>> int fadeout;
>> };
>>
>> The C++ code sets things up with:
>>
>> Q_DECLARE_METATYPE(QList<AudioSourceParameters>);
>>
>> and:
>>
>> qDBusRegisterMetaType<AudioSourceParameters>();
>> qDBusRegisterMetaType<QList<AudioSourceParameters> >();
>>
>> The introspection XML (presumably output by qdbuscpp2xml) shows this as
>> 'a(iiiii)'. That's what the client app (the one I'm trying to provide a
>> mock server for) is expecting to see.
>>
>> Any ideas how to make this work with PyQt?
>
> You probably can't using the QtDBus module because PyQt doesn't know
> anything about AudioSourceParameters.
>
> You should be able to use the standard Python dbus module which will
> bypass the Qt conversions.
>
> Phil
What clients expect is 'a(iiiii)', so the convenience type declared in
the C++ server I'm trying to mock out shouldn't matter for my purposes
(should it?)
It makes sense that PyQt wouldn't know anything about
'AudioSourceParameters', but can it handle 'a(iiiii)'? Or are D-Bus
arrays and structs (and arrays-of-structs) not supported?
I've seen a few PyQt code examples that use QDBusArgument to marshal
arbitrary arguments, but I haven't seen any examples where complex
objects are demarshalled.
This seems fine:
@pyqtSlot('QList<int>')
def func(self, args):
pass
but this:
@pyqtSlot('QList<QList<int> >')
def func(self, args):
pass
results in:
File "fake_hifi_audio.py", line 44, in HifiAudioServerAdaptor
@pyqtSlot('QList<QList<int> >')
TypeError: C++ type 'QList<QList<int> >' is not supported as a
pyqtSlot type argument type
If arrays of structs aren't supported, is there some way I can get the
thing that clients send as 'a(iiiii)' into a QDBusArgument variable and
demarshal it manually? PyQt's DBus bindings are *so* much better than
the standard python dbus module that I shudder at the thought of having
to go back to it... `:-}
More information about the PyQt
mailing list