在 D-Bus 适配程序中声明插槽
D-Bus 适配程序中插槽的声明方式与普通公共插槽相同,但其参数必须遵循特定规则(更多信息请参阅 Qt D-Bus 类型系统)。参数不符合这些规则或不是公用的插槽将无法通过 D-Bus 访问。
插槽可以有一个const QDBusMessage &
类型的参数,它必须出现在输入参数列表的末尾,任何输出参数之前。该参数(如果存在)将被初始化为当前正在处理的报文的副本,以便被调用者获取调用者的信息,如连接名称。
插槽有三种
- 异步
- 纯输入
- 输入-输出
异步插槽
异步槽通常不会向调用者返回任何回复。因此,它们不能接受任何输出参数。在大多数情况下,当槽的第一行运行时,调用者函数已经恢复工作。
但是,槽不能依赖这种行为。调度和消息分发问题可能会改变槽的运行顺序。打算与调用者同步的代码应提供自己的同步方法。
在void
返回类型和槽名之前,方法签名中的关键字Q_NOREPLY 会标记异步槽。D-Bus Complex Ping Pong示例中的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 。
© 2025 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.