我正在尝试使用Qt的QDBus调用WPA请求者的DBus接口(interface)
类库。特别是,我正在尝试使用“获取”属性
调用以检索“接口(interface)”属性值。
“获取”的DBus规范(通过自省(introspection))为:
<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类型)。对于“接口(interface)”属性,我是
期望变体是对象路径的数组(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
如何提取实际的消息数据?
最佳答案
我发现的最简单的方法是使用qDebug()
随手打印结果。这通常会指出您需要转换为下一个类型,直到您最终找到最里面的类型。
Qdbusviewer 是确定DBus参数的有用工具,
将被要求。在这种情况下:
在初始化
QDBusInterface
以调用Get
时,我们需要使用Properties
接口(interface),因为这是提供Get
的接口(interface)方法。
在使用
Get
方法调用QDBusInterface::call()
时,第二个和第三个参数对应于
内省(introspection)输出(
"interface"
和"propname"
)。 "interface"
是在哪里可以找到该属性,对于
"Interfaces"
属性是
"fi.w1.wpa_supplicant1"
(可以使用 qdbusviewer 确认)。"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
,其中包含我们的属性(property)信息。
qDebug() << result;
此调试语句打印:
QDBusMessage(type=MethodReturn, service=":1.2431", signature="v", contents=([Variant: [ObjectPath: /fi/w1/wpa_supplicant1/Interfaces/7/Networks/0]]) )
看起来挺好的。我们追求的是“ObjectPath”,它肯定在
在某处。
接下来,我们需要
QDBusMessage::arguments()
,“返回列表将要发送或从D-Bus接收的参数。”
返回
QList<QVariant>
。 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 vFirst = dbvFirst.variant();
qDebug() << vFirst;
我们似乎确实在转圈,但打印输出有点
这次不同:
QVariant(QDBusArgument, )
另一转换:
QDBusArgument dbusArgs = vFirst.value<QDBusArgument>();
不幸的是,
QVariant
在这里也不起作用。 qDebug()
type可以容纳许多不同的元素类型,下面对此进行了说明在Qt文档中。
QDBusArgument
告诉您哪个输入您的类型。在我们的情况下:
qDebug() << "QDBusArgument current type is" << dbusArgs.currentType();
打印:
QDBusArgument current type is 2
2表示
QDBusArgument::currentType()
。根据
ArrayType
文档,我们可以提取数组的元素使用如下代码:
QDBusObjectPath path;
dbusArgs.beginArray();
while (!dbusArgs.atEnd())
{
dbusArgs >> path;
// append path to a vector here if you want to keep it
}
dbusArgs.endArray();
我假设数组元素的类型为
QDBusArgument
,因为在这一点上,它使感觉如此。如果我是对的,那就很清楚了。
如果收到错误消息
QDBusObjectPath
,请将QDBusArgument: write from a read-only object
的声明更改为: const QDBusArgument &dbusArgs = vFirst.value<QDBusArgument>();
dbusArgs
也不支持qDebug()
,但是QDBusObjectPath
返回一个QDBusObjectPath::path()
,因此我们可以进行调试像这样打印:
qDebug() << path.path();
打印:
"/fi/w1/wpa_supplicant1/Interfaces/7"
终于!
关于c++ - 如何在Qt DBus调用中从QDBusMessage提取返回的数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20206376/