13

QDbusAbstractInterface上に(qdbusxml2cppを介して)構築されたQt DBusプロキシを使用して、開始時に使用できないようにインターフェイスするサービス/オブジェクトを処理するための最良の方法は何ですか?注:私は単にそれを知ることに興味はありません(BlahService.isValid()を使用してそれを見つけることができます)。それが有効かどうかを知り、いつ有効になるかを知りたいので、状態を変更して(そしてその状態変更を信号でブロードキャストして)、その状態変更で他のことを行うことができます。逆に、同様の理由で無効になった時期を知りたいのですが。

サービスの状態を追跡せずに:

#define CONNECT_DBUS_SIG(x,y) connect(blah,SIGNAL(x),this,SLOT(y))

// FIX - should watch for service, and also handle it going away and
// coming back
blah = new BlahService("com.xyzzy.BlahService", "/com/xyzzy/BlahService",
                           QDBusConnection::sessionBus(), this);
if (!blah)
    return 0;
if (blah.isValid())
{
    CONNECT_DBUS_SIG(foo(),Event_foo());
}
else
{
    // Since we aren't watching for registration, what can we do but exit?
}

おそらく、DBus接続オブジェクトでNameOwnerChangedを監視する必要があります(QTのdbusコードがこれを行わない限り)。次に、その信号変更状態を取得したら、必要に応じて、オブジェクトから信号を接続または切断します。

私が見つけたすべての例は、問題を無視するか、サーバーオブジェクトが存在しない場合は単に終了し、それがなくなることを処理しません。Car / Controller Qtの例では、少なくともサーバーが停止したかどうかに気づき、使用中にisValid()がfalseになると「Disconnected」と出力しますが、isValid()をポーリングしています。

追加した:

QtDbusAbtractInterfaceは、サーバーの所有権の変更(NameOwnerChanged)を登録し、変更が発生するとisValid()を更新することに注意してください。したがって、そのserverOwnerChangedシグナルに直接接続して、所有権の変更を確認し、それを再試行の指標として使用できると思います。ただし、シグナルを受け取る前または後に更新される可能性があるため、isValidを信頼することはできません。

または、(醜い)タイマーを設定してisValid()をポーリングすることもできます。

4

2 に答える 2

10

わかりました。誰も答えなかったので、その間に答えを見つけました。

NameOwnerChangedを見たい:

// subscribe to notifications about when a service is registered/unregistered
   connect(QDBusConnection::sessionBus().interface(),
           SIGNAL(serviceOwnerChanged(QString,QString,QString)),
           this,SLOT(serviceOwnerChanged(QString,QString,QString)));

void 
VcsApplicationController::serviceOwnerChanged(const QString &name,
                                              const QString &oldOwner,
                                              const QString &newOwner)
{
    Q_UNUSED(oldOwner);
    if (name == "com.foo.bar.FooService")
    {
        qLog(Whatever) << "serviceOwnerChanged" << name << oldOwner << newOwner;
        if (!newOwner.isEmpty())
        {
            // New owner in town
            emit Initialized();
            // or if you control the interface and both sides, you can wait for
            // a "Ready()" signal before declaring FooService ready for business.
        }
        else
        {
            // indicate we've lost connection, etc
            emit Uninitialized();
        }
    }
}

serviceOwnerChanged内からFooServiceでメソッドを実行すると競合状態が発生する可能性があることに注意してください-それらがバインディングの副作用(私のテストケースではdbus-c ++)なのか、dbusの設計に固有のものなのかはまだわかりません(可能性があります-dbusメーリングリストにない場合は質問に答えます)。実際の競合状態がある場合、DBus APIを制御していれば、Ready()/その他のシグナルを待つことができます。もう一方の端を制御しない場合は、非常に短い遅延を追加するか、AddMatch()を監視して、新しい所有者が名前に一致を追加したことを確認することもできます。

于 2009-09-24T14:02:12.030 に答える
4

Qt 5.3では、serviceOwnerChanged廃止されました。QDBusServiceWatcherすべてではなく特定のサービスを監視できるようにするために使用します。

于 2014-10-22T09:27:38.457 に答える