Я пытаюсь вызвать интерфейс DBus соискателя WPA, используя Qt QDBus
библиотека классов. В частности, я пытаюсь использовать свойство «Получить»
вызов для получения значения свойства «Интерфейсы».
Спецификация DBus (через самоанализ) для «Get»:
<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). Для свойства «Интерфейсы» я
ожидая, что вариант будет массивом путей к объектам (тип 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
интерфейс, так как это интерфейс, который обеспечивает Get
метод.
В вызове Get
с использованием QDBusInterface::call()
метод, второй и
третьи параметры соответствуют параметрам, перечисленным в
Самоанализ вывода ("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
,
который содержит информацию о нашей собственности в ловушке внутри.
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
тип.
QVariant vFirst = dbvFirst.variant();
qDebug() << vFirst;
Кажется, мы идем кругами, но вывод на печать немного
на этот раз по-другому:
QVariant(QDBusArgument, )
Другое преобразование:
QDBusArgument dbusArgs = vFirst.value<QDBusArgument>();
Unfortuately, qDebug()
здесь тоже не работает QDBusArgument
Тип может содержать несколько различных типов элементов, которые описаны
в документации Qt. QDBusArgument::currentType()
говорит вам, что
типа у вас есть. В нашем случае:
qDebug() << "QDBusArgument current type is" << dbusArgs.currentType();
печатает:
QDBusArgument current type is 2
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();
печатает:
"/fi/w1/wpa_supplicant1/Interfaces/7"
Наконец!
Других решений пока нет …