6

Qt の QDBus クラス ライブラリを使用して、WPA サプリカントの DBus インターフェイスを呼び出そうとしています。特に、「Get」プロパティ呼び出しを使用して「Interfaces」プロパティ値を取得しようとしています。

「Get」の 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>

十分に単純に思えます。2 つの文字列の入力と出力はバリアントです (これらは DBus 型です)。「Interfaces」プロパティについては、バリアントがオブジェクト パスの配列 (DBus タイプ「ao」) であると予想しています。

QDBusInterface::call()を返す DBus メソッドを呼び出すために使用していますQDBusMessageが、これからデータを抽出する方法がわかりません。

QDBusMessage::arguments()を返しますQList<QVariant>。オブジェクト パスの配列を見つけようとして、このリストの項目のさまざまな変換を試みましたが、代わりに空の文字列になってしまうようです。

QVariant::type()それは役立つはずですが、 type を返すように見えるだけで、QDBusMessage明らかに間違っています。例えば:

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

プリント:

Argument 0 type is QVariant::QDBusMessage

実際のメッセージ データを抽出するにはどうすればよいですか?

4

3 に答える 3

17

私が見つけた最も簡単な方法は、使用qDebug()して結果を印刷することです。これは通常、最終的に最も内側の型に到達するまで、次に変換する必要がある型を示します。

Qdbusviewerは、必要な DBus パラメータを決定するための便利なツールです。この場合:

  • WPAS サービス: "fi.w1.wpa_supplicant1"
  • WPAS パス: "/fi/w1/wpa_supplicant1"
  • プロパティ インターフェイス識別子: "org.freedesktop.DBus.Properties"
  • WPAS インターフェース識別子: "fi.w1.wpa_supplicant1"

QDBusInterfaceを呼び出すために を初期化する際には、メソッドを提供するインターフェイスであるため、インターフェイスGetを使用する必要があり ます 。PropertiesGet

Getメソッドを使用して呼び出す場合、2 番目と 3 番目のパラメーターは、イントロスペクションの出力 (および)QDBusInterface::call()にリストされているパラメーターに対応します。プロパティを見つけることができる場所です(これはqdbusviewerを使用して確認できます)。"interface""propname""interface""Interfaces""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;

このデバッグ ステートメントは次を出力します。

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>();

残念ながら、qDebug()ここでも機能しません。タイプは、QtのQDBusArgument ドキュメントで説明されているさまざまな要素タイプを保持できます。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"

やっと!

于 2013-11-26T00:34:44.453 に答える