Как извлечь возвращенные данные из QDBusMessage в вызове Qt DBus?

Я пытаюсь вызвать интерфейс 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

Как извлечь фактические данные сообщения?

4

Решение

Самый простой способ, который я нашел, это использовать qDebug() печатать результаты, как вы идете. Обычно это указывает на то, какой тип вам нужно преобразовать в следующий, пока вы, наконец, не достигнете самого внутреннего типа.

Qdbusviewer является полезным инструментом для определения параметров DBus, которые
потребуется. В этом случае:

  • WPAS Сервис: «Fi.w1.wpa_supplicant1»
  • WPAS Path: «/ Ц / w1 / wpa_supplicant1»
  • Идентификатор интерфейса свойств: «org.freedesktop.DBus.Properties»
  • Идентификатор интерфейса WPAS: «Fi.w1.wpa_supplicant1»

В инициализации 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"

Наконец!

11

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]