如何在Qt DBus调用中从QDBusMessage中提取返回的数据?

时间:2013-11-26 00:34:44

标签: c++ dbus qtdbus qdbus

我正在尝试使用Qt的QDBus调用WPA请求者的DBus接口 班级图书馆。特别是,我正在尝试使用“获取”属性 调用以检索“Interfaces”属性值。

“获取”的DBus规范(通过内省)是:

<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>

看起来很简单。输入两个字符串,输出为a 变体(这些是DBus类型)。对于“接口”属性,我是 期望变量是一个对象路径数组(DBus类型“ao”)。

我正在使用QDBusInterface::call()来调用DBus方法 返回QDBusMessage,但我无法弄清楚如何提取数据 从此。

QDBusMessage::arguments()返回QList<QVariant>。我试过了 对此列表中的项目进行各种转换以尝试查找我的 对象路径数组,但我似乎最终得到一个空字符串 代替。

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

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

打印:

Argument 0 type is QVariant::QDBusMessage

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

3 个答案:

答案 0 :(得分:11)

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

Qdbusviewer 是确定DBus参数的有用工具 将被要求。在这种情况下:

  • WPAS服务:“fi.w1.wpa_supplicant1”
  • WPAS路径:“/ fi / w1 / wpa_supplicant1”
  • 属性界面标识符:“org.freedesktop.DBus.Properties”
  • WPAS接口标识符:“fi.w1.wpa_supplicant1”

在初始化调用QDBusInterface的{​​{1}}时,我们需要使用。{ Get接口,因为这是提供Properties的接口 方法

使用Get方法调用Get,第二个和 第三个参数对应于中列出的参数 内省输出(QDBusInterface::call()"interface")。 "propname"是 可以找到属性的地方,"interface"属性 是"Interfaces"(可以使用 qdbusviewer 确认。)

"fi.w1.wpa_supplicant1"参数只是属性的名称: 在这种情况下"propname"

到目前为止的代码:

"Interfaces"

这是困难的部分。 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

此调试语句打印:

    qDebug() << result;

看起来不错。 “ObjectPath”是我们追求的目标,而且它肯定在 在某个地方。

接下来我们需要QDBusMessage(type=MethodReturn, service=":1.2431", signature="v", contents=([Variant: [ObjectPath: /fi/w1/wpa_supplicant1/Interfaces/7/Networks/0]]) ) ,其中“返回列表 将要发送或从D-Bus收到的参数。“它 返回QDBusMessage::arguments()

QList<QVariant>

debug语句打印:

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

这个“符号”有点不清楚(括号是指列表?),但我们会 继续。

(QVariant(QDBusVariant, ) )

打印:

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

所以外部括号似乎表示一个数组,尽管为什么会这样 是内部集合中使用的逗号,而不是外部集合中的逗号 一个谜。

我们在遇到它们时会不断转换类型:

QVariant(QDBusVariant, )

QDBusVariant dbvFirst = first.value<QDBusVariant>(); //qDebug() << dbvFirst; // compile error! 无法理解qDebug(),因此没有调试打印 可以在这里相反,如果我们查看文档 QDBusVariant,我们发现它提供了QDBusVariant方法 转换为常规variant()类型。

QVariant

我们似乎确实在圈子里,但打印输出有点 这次不同:

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

另一次转换:

QVariant(QDBusArgument, )

不幸的是, QDBusArgument dbusArgs = vFirst.value<QDBusArgument>(); 在这里也不起作用。 qDebug() type可以包含许多不同的元素类型,这些元素类型都有描述 在Qt文档中。 QDBusArgument告诉你哪个 你有类型。在我们的案例中:

QDBusArgument::currentType()

打印:

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

2表示QDBusArgument current type is 2

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

QDBusArgument

我假设数组元素类型是 QDBusObjectPath path; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { dbusArgs >> path; // append path to a vector here if you want to keep it } dbusArgs.endArray(); ,因为此时它是。{ 感觉就是这样。如果我是对的,那就很清楚了。

如果收到错误消息QDBusObjectPath,请将QDBusArgument: write from a read-only object的声明更改为:

dbusArgs

const QDBusArgument &dbusArgs = vFirst.value<QDBusArgument>(); 也不支持qDebug(),但是 QDBusObjectPath返回QDBusObjectPath::path(),因此我们可以进行调试 像这样打印:

QString

打印:

    qDebug() << path.path();

最后!

答案 1 :(得分:0)

我的目标是获取GetInterface接口的fi.w1.wpa_supplicant1方法返回的对象路径。

@MatthewD的回答确实有助于我开始实验,但不幸的是,它并没有按要求为我工作。我尝试了所有可能。但是最后,以某种方式,我以一种不同且相当短的方式获得了所需的结果。

我所做的是:
-我有一个界面:
  QDBusInterface interface("fi.w1.wpa_supplicant1", "/fi/w1/wpa_supplicant1", "fi.w1.wpa_supplicant1", QDBusConnection::systemBus());

-调用方法并存储消息
  QDBusMessage mesg = interface.call("GetInterface", "wlan0");

-然后得到第一个参数
  QVariant var = mesg.arguments().at(0);

-然后获取对象路径
  QDBusObjectPath objpath = var.value<QDBusObjectPath>();

-最后
  QString path_str = objpath.path();

现在将路径打印为字符串:
printf("Object path: %s\n", path_str);

答案 2 :(得分:0)

好吧,经过这么长时间!

我认为在调试回复并看到它的 QDBusVariant ...

variant() 结果的 QDBusVariant 方法返回 QDBus Variant 作为 QVariant 对象..因此,调用:

const auto &resultArg = result.arguments().at(0).value<QDBusVariant>().variant();

返回一个 QVariant ..,我们可以在调试中轻松打印或转换为对象中的存储值。