Вопрос

С прокси-сервером 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 не сделает это за нас - а затем, когда мы получим этот сигнал, измените состояние и, при необходимости, подключите или отключите сигналы от объекта.

Все примеры, которые я нахожу, либо игнорируют проблему, либо просто завершают работу, если серверный объект не существует, и не имеют дела с его исчезновением.Пример Car / Controller Qt, по крайней мере, замечает, если сервер отключается, и печатает "Отключен", если isValid() становится ложным во время использования, но он опрашивает isValid().

Добавленный:

Обратите внимание, что QtDbusAbtractInterface регистрирует изменения владельца сервера (NameOwnerChanged) и обновляет isValid() при возникновении изменений.Поэтому я подозреваю, что вы можете напрямую подключиться к этому сигналу serverOwnerChanged, чтобы узнать об изменении владельца, и использовать это как индикатор для повторной попытки - хотя вы не сможете доверять isValid, поскольку он может быть обновлен до или после получения вами сигнала.

В качестве альтернативы (некрасиво) вы можете настроить таймер и опрос для isValid().

Это было полезно?

Решение

Хорошо, поскольку никто не ответил, я тем временем нашел ответ:

Вы хотите посмотреть 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 не ответит на вопрос).Если там является в реальном состоянии гонки вы можете дождаться сигнала Ready() / любого другого, если вы управляете DBus API.Если вы не управляете другим концом, вы можете добавить очень короткую задержку или вы также можете просмотреть AddMatch(), чтобы убедиться, что новый владелец добавил совпадение и по имени.

Другие советы

С Qt 5.3, serviceOwnerChanged является устаревшим.Использование QDBusServiceWatcher который позволяет отслеживать конкретную услугу, а не все.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top