Ожидание службы DBus, которая будет доступна в Qt
с прокси-сервером Qt DBus, построенным на QDbusAbstractInterface (через qdbusxml2cpp), каков наилучший способ обработки сервиса/объекта, который вы хотите подключить к недоступности при запуске? Примечание: мне не интересно просто знать это (вы можете использовать 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?
}
вероятно, нам нужно следить за NameOwnerChanged на объекте соединения DBus-если только код dbus QT не делает этого для нас - а затем, когда мы получим этот сигнал, измените состояние, и при необходимости подключите или отключите сигналы от объекта.
все примеры, которые я нахожу, либо игнорируют проблему, либо просто выходят, если объект сервера не существует, и не переживай, что это пройдет. Пример автомобиля / контроллера Qt, по крайней мере, замечает, что сервер уходит и печатает "отключен", если isValid() становится ложным во время использования, но это опрос isValid().
добавлено:
обратите внимание, что qtdbusabtractinterface регистрирует изменения владения сервером (NameOwnerChanged) и обновляет isValid() при возникновении изменений. Поэтому я подозреваю, что вы можете подключиться к этому сигналу serverOwnerChanged напрямую, чтобы узнать об изменениях в собственности и используйте это как индикатор для повторной попытки , хотя вы не сможете доверять isValid, так как он может быть обновлен до или после сигнала.
альтернативно (уродливо) вы можете настроить таймер и опрос для isValid ().
2 ответов
хорошо, так как никто не ответил, я нашел ответ тем временем:
вы хотите посмотреть 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();
}
}
}
обратите внимание, что есть мая быть условиями гонки с методами выполнения на FooService из serviceOwnerChanged-я еще не уверен, являются ли они побочным эффектом привязки (dbus-C++ в моем тестовом случае) или присущими дизайну dbus (возможно-нет в списке рассылки dbus ответит на вопрос). Если есть is реальное состояние гонки, вы можете ждать сигнала Ready () / whatever, если вы управляете API DBus. Если вы не контролируете другой конец, вы можете добавить очень короткую задержку или также посмотреть AddMatch (), чтобы убедиться, что новый владелец добавил совпадение по имени.
С Qt 5.3, serviceOwnerChanged
устарела. Использовать QDBusServiceWatcher
что позволяет следить за конкретной службой вместо всех.