QtDBus Proxy 訪問遠端物件與回傳值 demarshall
在之前的文章[1]裡,我提到QtDBus在叫用DBus上的方法時,對輸入參數和輸出參數的資料型態必須做marshall和demarshall,而且有點不太容易。有些人會説,你只使用QDBusMessage來叫用方法以及接收回傳值,這不是Qt建議的作法!用QDBusMessage來做太低階了,所以參數的型態才要轉換的那麼辛苦。
因此,我要使用Qt建議的Proxy類别[2]做法來試試看,是不是比較容易一些。首先,之前討讑提到的輸入參數資料型態為object path時,必須自己使用QVariant::fromValue(object_path)將資料填入參數列中。使用Proxy類别做法,在使用qdbusxml2cpp工具産生需要的proxy類别後,我們可以很直觀的使用以下語法,將資料型態為QDBusObjectPath的變數,直接送入輸入參數資料型態為object path的方法中。
看一下qdbusxml2cpp工具産生的類别proxy程式,可以看到如下一段程式,原來是這個proxy類别幫我自動做了同様的轉換工作。
那麼複雜的參數型態呢?是不是也可以幫我們一點忙呢?
我們來看一下之前討讑的字典中有矩陣的問題,許多的DBus方法中,特别是取得屬性的方法,通常是叫做GetProperties(),它的回傳值都是一個字典(a{sv}),而且其中有一些值,其實是個矩陣。一様的問題,用Proxy類别的作法可以取得字典的回傳值。但我要取得其中一個值的矩陣,要如何做呢?如下片斷程式,利用qDebug()來看一下回傳值的内容。
參考來源:
[1] 小白和小叮叮, QtDBus marshall and demarshall, 2013/10/8
[2] wwang, D-BUS和QT4, 2010/10/27
因此,我要使用Qt建議的Proxy類别[2]做法來試試看,是不是比較容易一些。首先,之前討讑提到的輸入參數資料型態為object path時,必須自己使用QVariant::fromValue(object_path)將資料填入參數列中。使用Proxy類别做法,在使用qdbusxml2cpp工具産生需要的proxy類别後,我們可以很直觀的使用以下語法,將資料型態為QDBusObjectPath的變數,直接送入輸入參數資料型態為object path的方法中。
proxy.Method(object_path);真是太好了,這様大家都輕鬆許多。
看一下qdbusxml2cpp工具産生的類别proxy程式,可以看到如下一段程式,原來是這個proxy類别幫我自動做了同様的轉換工作。
inline QDBusPendingReply<> Method(const QDBusObjectPath &device)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(device);
return asyncCallWithArgumentList(QLatin1String("Method"), argumentList);
}
其實不管Qt是如何做到的,只要能減輕我們的工作就好了。那麼複雜的參數型態呢?是不是也可以幫我們一點忙呢?
我們來看一下之前討讑的字典中有矩陣的問題,許多的DBus方法中,特别是取得屬性的方法,通常是叫做GetProperties(),它的回傳值都是一個字典(a{sv}),而且其中有一些值,其實是個矩陣。一様的問題,用Proxy類别的作法可以取得字典的回傳值。但我要取得其中一個值的矩陣,要如何做呢?如下片斷程式,利用qDebug()來看一下回傳值的内容。
QDBusPendingReply<QVariantMap> reply = proxy.GetProperties(); reply.waitForFinished(); qDebug() << reply.value();結果是:
QMap(("Address", QVariant(QString, "00:1A:7D:xx:xx:xx") ) ( "Class" , QVariant(uint, 0) ) ( "XXXX" , QVariant(QDBusArgument, ) ) ( "Discoverable" , QVariant(bool, false) ) ( "DiscoverableTimeout" , QVariant(uint, 0) ) ( "Discovering" , QVariant(bool, false) ) ( "Name" , QVariant(QString, "ubuntu-x") ) ( "Pairable" , QVariant(bool, true) ) ( "PairableTimeout" , QVariant(uint, 0) ) ( "Powered" , QVariant(bool, true) ) ( "UUIDs" , QVariant(QStringList, ("00001000-0000-1000-8000-00805f9bxxxx", "00001001-0000-1000-8000-00805f9bxxxx", "0000112d-0000-1000-8000-00805f9xxxxb", "00001112-0000-1000-8000-00805f9xxxxb", "0000111f-0000-1000-8000-00805f9xxxxb") ) ) )
重點是,我們要的Key為"XXXX"的屬性,其值部份的資料型態仍然為QVariant(QDBusArgument),也就是説,我們還是要自行做轉型的工作。而轉型的方法,目前我覺得就是用前文討讑的方法,由QDBusArgument的成員函數beginArray(), atEnd(), asVariant()來完成。除此之外,不知道是不是有其他更好的方法了!參考來源:
[1] 小白和小叮叮, QtDBus marshall and demarshall, 2013/10/8
[2] wwang, D-BUS和QT4, 2010/10/27
留言