D-Bus适配器中声明槽

D-Bus适配器中的槽声明与常规的公共槽类似,但它们的参数必须遵循某些规则(详细信息请参见Qt D-Bus类型系统)。不遵循这些规则或不是公共的槽将无法通过D-Bus访问。

槽可以有一个参数类型为const QDBusMessage &,该参数必须出现在输入参数列表的最后,在所有输出参数之前。如果存在该参数,它将初始化为正在处理的当前消息的副本,这允许被调用者获取有关调用者信息,例如其连接名称。

槽可以是三种类型之一

  1. 异步
  2. 仅输入
  3. 输入和输出

异步槽

异步槽通常不向调用者返回任何回复。因此,它们不能接受任何输出参数。在大多数情况下,在槽的第一行运行时,调用函数已经恢复工作。

然而,槽不得依赖于该行为。调度和消息分派问题可能会改变槽的运行顺序。打算与调用者同步的代码应提供自己的同步方法。

异步槽在方法签名中以关键字Q_NOREPLY标记,在void返回类型和槽名称之前。在D-Bus Complex Ping Pong示例中,quit()槽是这种类型的示例。

仅输入槽

仅输入槽是接受通过值或通过常量引用传递的参数的常规槽。然而,与异步槽不同,调用者通常在完成调用者之前才会继续操作。因此,非异步槽不应阻塞或应在其文档中明确表示可能会阻塞。

仅输入槽在其签名中没有特殊标记,除了它们仅接受通过值或通过常量引用传递的参数。可选地,槽可以接受一个作为最后一个参数的QDBusMessage参数,可用于执行对方法调用消息的附加分析。

输入和输出槽

类似于只输入接口 slot,输入输出接口 slot 是调用方等待回复的。但与只输入的相比,这个回复将包含数据。可能输出数据的 slot 可能包含非常量引用,也可能返回一个值。然而,输出参数必须位于参数列表的末尾,并且不能有输入参数混入。可选地,可以在输入和输出参数之间出现一个 QDBusMessage 参数。

自动回复

方法回复是由 Qt D-Bus 实现根据输出参数的内容(如果有的话)自动生成的。slot 不需要担心构造合适的 QDBusMessage 对象并通过连接发送它们。

然而,这样做是有可能的。如果 slot 发现它需要发送特殊的回复甚至错误,它可以通过在 QDBusMessage 参数上使用 QDBusMessage::createReply() 或 QDBusMessage::createErrorReply() 并通过 QDBusConnection::send() 发送来做到这一点。Qt D-Bus 实现如果 slot 这样做了,将不会生成任何回复。

警告:调用方放置一个方法调用并等待回复时,它只会等待一定的时间。打算执行很长时间的槽应该在该文档中指出这一点,以便调用方设置较高的超时时间。

延迟回复

在某些情况下,被调用的 slot 可能无法立即处理请求。这通常是涉及 I/O 或网络操作的情况,这些操作可能会阻塞。

如果情况如此,slot 应该将控制权交回应用程序的主循环以避免冻结用户界面,稍后再继续处理。为了实现这一点,它应该使用输入参数列表末尾的额外 QDBusMessage 参数并请求延迟回复。

我们通过编写一个槽来做到这一点,这个槽将请求数据存储在持久结构中,并使用 QDBusMessage::setDelayedReply(true) 通知调用方响应将在稍后发送。

struct RequestData
{
    QString request;
    QString processedData;
    QDBusMessage reply;
};

QString processRequest(const QString &request, const QDBusMessage &message)
{
    RequestData *data = new RequestData;
    data->request = request;
    message.setDelayedReply(true);
    data->reply = message.createReply();

    appendRequest(data);
    return QString();
}

在这种情况下,返回值是不重要的;我们返回一个任意值以满足编译器。

当请求被处理并且有回复可用时,应该使用获得的 QDBusMessage 对象发送回复。在我们的示例中,回复代码可能如下所示

void sendReply(RequestData *data)
{
    // data->processedData has been initialized with the request's reply
    QDBusMessage &reply = data->reply;

    // send the reply over D-Bus:
    reply << data->processedData;
    QDBusConnection::sessionBus().send(reply);

    // dispose of the transaction data
    delete data;
}

如示例所示,当设置延迟回复时,Qt D-Bus 会忽略槽的返回值。这些值仅用于在与远程应用程序通信时确定槽的签名,或者如果槽中的代码决定不使用延迟回复。

延迟回复本身就是通过在原始消息上调用 QDBusMessage::reply() 从 Qt D-Bus 请求的。然后,向调用方发送回复成为调用代码的责任。

警告:调用方放置一个方法调用并等待回复时,它只会等待一定的时间。打算执行很长时间的槽应该在该文档中指出这一点,以便调用方设置较高的超时时间。

另请参阅:使用 Qt D-Bus 适配器在 D-Bus 适配器中声明信号Qt D-Bus 类型系统QDBusConnectionQDBusMessage

© 2024 The Qt Company Ltd. 本文档中包含的贡献资料归属其各自所有者。提供的文档根据自由软件基金会发布的GNU自由文档许可 versión 1.3 进行许可。Qt及其相关商标是芬兰及全球其他国家的The Qt Company Ltd.的商标。所有其他商标归其各自所有者所有。