本页内容

在 D-Bus 适配器中声明插槽

D-Bus适配器中的插槽声明方式与普通的公共插槽相同,但其参数必须遵循特定规则(更多信息请参阅《Qt D-Bus 类型系统》)。参数不符合这些规则或非公共的插槽将无法通过D-Bus访问。

插槽可以包含一个类型为const QDBusMessage & 的参数,该参数必须位于输入参数列表的末尾,且在任何输出参数之前。如果存在此参数,它将被当前正在处理的消息的副本初始化,这使得被调用方能够获取关于调用方的信息,例如其连接名称。

插槽可分为三种类型:

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

异步插槽

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

然而,插槽绝不能依赖这种行为。调度与消息分发问题可能会改变插槽的执行顺序。旨在与调用方同步的代码应提供自己的同步方法。

异步插槽在方法签名中通过关键字Q_NOREPLY 进行标记,该关键字位于返回类型void 和插槽名称之前。D-Bus“复杂乒乓”示例中的quit() 插槽便是此类示例。

仅输入槽

仅输入槽是普通槽,接受按值传递或常量引用传递的参数。然而,与异步槽不同,调用方通常会在被调用方完成操作后才继续执行。因此,非异步槽不应阻塞,或者应在文档中明确说明其可能会阻塞。

仅输入槽在签名中没有特殊标记,只是它们仅接受按值传递或常量引用传递的参数。可选地,槽可以将QDBusMessage 参数作为最后一个参数,该参数可用于对方法调用消息进行额外分析。

输入和输出槽

与仅输入槽类似,输入/输出槽是指调用方正在等待响应的槽。但与仅输入槽不同的是,该响应将包含数据。输出数据的槽可以包含非常量引用,也可以返回一个值。 但是,输出参数必须全部出现在参数列表的末尾,且不得与输入参数交错出现。可选地,QDBusMessage 参数可出现在输入参数与输出参数之间。

自动回复

方法响应由Qt D-Bus 实现自动生成,内容来自输出参数(如有)。插槽无需担心构建正确的QDBusMessage 对象并通过连接发送它们。

不过,这种操作的可能性依然存在。如果插槽发现需要发送特殊回复甚至错误,它可以通过对QDBusMessage 参数调用QDBusMessage::createReply()或QDBusMessage::createErrorReply(),并使用QDBusConnection::send()将其发送出去。如果插槽这样做了,Qt D-Bus 的实现将不会生成任何回复。

警告:当 调用方发出方法调用并等待响应时 ,其等待时间是有限的。预计执行时间较长的插槽应在文档中明确说明这一点,以便调用方正确设置更长的超时时间。

延迟响应

在某些情况下,被调用的插槽可能无法立即处理请求。当请求涉及可能导致阻塞的 I/O 或网络操作时,这种情况尤为常见。

如果出现这种情况,该插槽应将控制权交还给应用程序的主循环,以避免用户界面冻结,并稍后恢复处理。为实现这一点,它应利用输入参数列表末尾的额外参数 `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 类型系统》、《QDBusConnection 》以及《QDBusMessage 》。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.