本文介绍了如何在Qt DBus调用中从QDBusMessage提取返回的数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试使用Qt的QDBus
类库来调用WPA请求者的DBus接口。特别是,我试图使用 Get属性
调用来检索 Interfaces属性值。

I'm trying to call WPA supplicant's DBus interface using Qt's QDBusclass library. In particular, I'm trying to use the "Get" propertycall to retrieve the "Interfaces" property value.

DBus规范(通过自省) 获取的含义是:

The DBus specification (via introspection) for "Get" is:

<interface name="org.freedesktop.DBus.Properties">
    <method name="Get">
        <arg name="interface" type="s" direction="in"/>
        <arg name="propname" type="s" direction="in"/>
        <arg name="value" type="v" direction="out"/>
    </method>
    ...
</interface>

似乎很简单。输入两个字符串,输出是
变体(这些是DBus类型)。对于 Interfaces属性,我是
,期望该变量是对象路径的数组(DBus类型为 ao)。

Seems simple enough. Two strings input and the output is avariant (these are DBus types). For the "Interfaces" property I'mexpecting the variant to be an array of object paths (DBus type "ao").

我正在使用 QDBusInterface :: call()调用DBus方法,其中
返回 QDBusMessage ,但是我可以

I'm using QDBusInterface::call() to call the DBus method, whichreturns a QDBusMessage, but I can't figure out how to extract my datafrom this.

QDBusMessage :: arguments()返回 QList< QVariant> 。我已经尝试了
列表中各项的各种转换,以试图找到我的
对象路径数组,但是我似乎最终得到的是空字符串

QDBusMessage::arguments() returns a QList<QVariant>. I've triedvarious conversions of the items in this list in an attempt to find myarray of object paths, but I just seem to end up with an empty stringinstead.

QVariant :: type()似乎应该有所帮助,但似乎只是
返回类型 QDBusMessage ,这显然是错误的。例如:

QVariant::type() seems like it should help, but it only seems toreturn the type QDBusMessage, which is clearly wrong. For example:

// 'message' is of type QDBusMessage
qDebug() << "Argument 0 type is" << message.arguments().at(0).type();

打印:

Argument 0 type is QVariant::QDBusMessage

如何提取实际的消息数据?

How do I extract the actual message data?

推荐答案

我找到的最简单的方法是使用 qDebug()随时打印结果。这通常会指向您需要转换为下一个的类型,直到您最终找到最里面的类型。

The easiest way I've found is to use qDebug() to print results as you go. This usually points you to which type you need to convert to next, until you finally reach the innermost type.

Qdbusviewer 是一个有用的工具确定需要
的DBus参数。在这种情况下:

Qdbusviewer is a useful tool for determining the DBus parameters thatwill be required. In this case:


  • WPAS服务: fi.w1.wpa_supplicant1

  • WPAS路径: / fi / w1 / wpa_supplicant1

  • 属性接口标识符: org.freedesktop.DBus.Properties

  • WPAS接口标识符: fi.w1.wpa_supplicant1

  • WPAS Service: "fi.w1.wpa_supplicant1"
  • WPAS Path: "/fi/w1/wpa_supplicant1"
  • Properties interface identifier: "org.freedesktop.DBus.Properties"
  • WPAS interface identifier: "fi.w1.wpa_supplicant1"

在初始化 QDBusInterface 以调用 Get 时,我们需要使用
Properties 接口,因为该接口提供了 Get
方法。

In initialising the QDBusInterface for calling Get, we need to use theProperties interface, since that's the interface that provides the Getmethod.

使用 QDBusInterface :: call()方法调用 Get 时,第二个和
第三个参数对应于
内省输出中列出的参数(接口 属性名 )。 接口 是可以在其中找到属性的
,对于接口 属性
fi.w1.wpa_supplicant1 (可以使用 qdbusviewer 确认)。

In calling Get using the QDBusInterface::call() method, the second andthird parameters correspond to the parameters listed in theIntrospection output ("interface" and "propname"). "interface" iswhere the property can be found, which for the "Interfaces" propertyis "fi.w1.wpa_supplicant1" (this can be confirmed using qdbusviewer).

属性名 参数只是属性的名称:
接口

The "propname" parameter is just the name of the property:"Interfaces" in this case.

到目前为止的代码:

std::string getInterface()
{
    QDBusInterface interface( "fi.w1.wpa_supplicant1",
                              "/fi/w1/wpa_supplicant1",
                              "org.freedesktop.DBus.Properties",
                              QDBusConnection::systemBus() );

    // Calls DBus method
    QDBusMessage result = interface.call( "Get",
                                          "fi.w1.wpa_supplicant1",
                                          "Interfaces" );

这是困难的部分。 QDBusInterface :: call()返回 QDBusMessage
,其中包含我们的财产信息。

This is the hard part. QDBusInterface::call() returns a QDBusMessage,which has our property information trapped within.

    qDebug() << result;

此调试语句打印:

QDBusMessage(type=MethodReturn, service=":1.2431", signature="v", contents=([Variant: [ObjectPath: /fi/w1/wpa_supplicant1/Interfaces/7/Networks/0]]) )

看起来不错。 ObjectPath就是我们所追求的,而且肯定在
中。

Looks good. The "ObjectPath" is what we're after, and it's definitely inthere somewhere.

接下来,我们需要 QDBusMessage :: arguments (),其中返回要从D-Bus发送或接收的
参数列表。

返回一个 QList< QVariant>

Next we need QDBusMessage::arguments(), which "Returns the list ofarguments that are going to be sent or were received from D-Bus." Itreturns a QList<QVariant>.

    QList<QVariant> outArgs = result.arguments();
    qDebug() << outArgs;

调试语句打印:

(QVariant(QDBusVariant, ) )

不清楚(方括号是否表示列表?),但我们将继续

This 'notation' is a bit unclear (do brackets mean lists?), but we'llkeep going.

    QVariant first = outArgs.at(0);
    qDebug() << first;

打印:

QVariant(QDBusVariant, )

因此,方括号似乎表示一个数组,尽管为什么
是内部集合而不是外部集合使用的逗号有点
a的奥秘。

So the outer brackets do seem to indicate an array, though why thereis a comma used in the inner set and not in the outer set is a bit ofa mystery.

我们一直在转换类型当我们遇到它们时:

We keep converting types as we come across them:

    QDBusVariant dbvFirst = first.value<QDBusVariant>();
    //qDebug() << dbvFirst; // compile error!

qDebug()不理解 QDBusVariant ,因此此处没有调试打印
。相反,如果我们查看
QDBusVariant 的文档,我们会发现它提供了 variant()方法将
转换为常规 QVariant 类型。

qDebug() doesn't understand QDBusVariant, so no debug print isavailable here. Instead if we look at the documentation forQDBusVariant, we see that it provides a variant() method forconverting to a regular QVariant type.

    QVariant vFirst = dbvFirst.variant();
    qDebug() << vFirst;

我们似乎盘旋了一下,但是打印输出与
有点不同这次:

We do seem to be going in circles, but the print output is a bitdifferent this time:

QVariant(QDBusArgument, )

另一种转换:

    QDBusArgument dbusArgs = vFirst.value<QDBusArgument>();

不幸的是, qDebug()并不也可以在这里工作。 QDBusArgument
类型可以容纳许多不同的元素类型,这些元素类型在Qt文档中描述为
QDBusArgument :: currentType()告诉您具有哪种
类型。在我们的示例中:

Unfortuately, qDebug() doesn't work here either. The QDBusArgumenttype can hold a number of different element types, which are describedin the Qt documentation. QDBusArgument::currentType() tells you whichtype you have. In our case:

    qDebug() << "QDBusArgument current type is" << dbusArgs.currentType();

打印:

QDBusArgument current type is 2

2表示 ArrayType

根据 QDBusArgument 文档,我们可以提取以下内容的
元素:使用以下代码的数组:

According to the QDBusArgument documentation, we can extract theelements of the array using code like the following:

    QDBusObjectPath path;
    dbusArgs.beginArray();
    while (!dbusArgs.atEnd())
    {
        dbusArgs >> path;
        // append path to a vector here if you want to keep it
    }
    dbusArgs.endArray();

我假设数组元素类型为 QDBusObjectPath ,因为在这一点上,
是合理的。

I've assumed the array element type is QDBusObjectPath, since at this point it makessense for it to be so. It'll be clear if I'm right.

如果收到错误消息 QDBusArgument:从只读对象写入,将 dbusArgs 的声明更改为:

If you get the error message QDBusArgument: write from a read-only object, change the declaration of dbusArgs to:

    const QDBusArgument &dbusArgs = vFirst.value<QDBusArgument>();

qDebug()不支持 QDBusObjectPath ,但是
QDBusObjectPath :: path()返回 QString ,因此我们可以像下面这样获得调试
的打印内容:

qDebug() doesn't support QDBusObjectPath either, butQDBusObjectPath::path() returns a QString, so we can get our debugprint like this:

    qDebug() << path.path();

打印:

"/fi/w1/wpa_supplicant1/Interfaces/7"

最后!

这篇关于如何在Qt DBus调用中从QDBusMessage提取返回的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-14 21:40