警告
本节包含自动从C++转换为Python的代码片段,可能包含错误。
在D-Bus适配器中声明槽#
D-Bus适配器中的槽与常规、公共槽一样声明,但它们的参数必须遵循某些规则(更多信息请参阅Qt D-Bus类型系统)。不符合这些规则的槽或非公共槽无法通过D-Bus访问。
槽可以有一个类型为const QDBusMessage &
的参数,这个参数必须出现在输入参数列表的末尾,在所有输出参数之前。如果存在此参数,它将被初始化为当前正在处理的消息的副本,这允许调用方获取有关调用者的信息,如连接名称。
槽可以是三种类型之一
异步
输入唯一
输入和输出
异步槽#
异步槽在正常情况下不会向调用者返回任何回复。因此,它们不能接受任何输出参数。在大多数情况下,在槽的第一行运行时,调用者的函数已经恢复工作。
然而,槽不应依赖于这种行为。调度和消息分派问题可能会改变槽运行的顺序。打算与调用者同步的代码应提供自己的同步方法。
异步槽在方法签名中使用关键字Q_NOREPLY
标记,位于返回类型void
和数据槽名称之前。在D-Bus Complex Ping Pong示例中的quit()
数据槽是一个示例。
输入唯一槽#
输入唯一槽是接受通过值传递或通过常量引用传递的参数的常规槽。然而,与异步槽不同,调用者通常在继续操作之前等待被调用者的完成。因此,非异步槽不应阻塞或应在文档中明确说明可能阻塞。
输入唯一槽在其签名中没有特殊标记,除了它们只接受通过值传递或通过常量引用传递的参数。可选地,槽可以接受一个作为最后一个参数的QDBusMessage
参数,可用于对方法调用消息进行附加分析。
输入和输出槽#
类似于单输入槽,输入输出槽是调用方等待回复的槽位。然而,与仅输入槽不同的是,这个回复将包含数据。可以输出数据的槽位可能包含非常量引用,也可能返回一个值。但是,输出参数必须全部出现在参数列表的末尾,且不得与输入参数混合。可选地,在输入和输出参数之间可以出现一个 QDBusMessage
参数。
自动回复#
方法回复是由 Qt D-Bus 实现自动生成的,包括输出参数的内容(如果有的话)。槽不需要担心构造正确的 QDBusMessage
对象并将它们通过连接发送。
但是,仍然有机会这样做。如果槽发现需要发送特殊的回复,甚至错误,可以通过在 QDBusMessage
参数上使用 createReply()
或 createErrorReply()
,并通过 send()
发送它。Qt D-Bus 实现不会生成任何回复,如果槽这样做的话。
警告
当一个调用方发出方法调用来等待回复时,它只会等待有限的时间。如果槽需要花费很长时间来完成,应该在文档中明确这一点,以便调用方可以适当设置更长的超时时间。
延迟回复#
在某些情况下,被调用的槽可能无法立即处理请求。这通常是涉及 I/O 或网络操作的情况,这些操作可能会阻塞。
如果是这种情况,该槽应将控制权交回应用程序的主循环以避免冻结用户界面,稍后再继续处理。为了实现这一点,它应该利用输入参数列表末尾的额外 QDBusMessage
参数,并请求延迟回复。
我们通过编写一个槽位来存储请求数据到持久结构中,并使用 setDelayedReply(true)
通知调用方,响应将在稍后发送。
class RequestData(): request = QString() processedData = QString() reply = QDBusMessage() def processRequest(request,message): data = RequestData() data.request = request message.setDelayedReply(True) data.reply = message.createReply() appendRequest(data) return QString()
在这种情况下,返回值无关紧要;我们返回一个任意值以满足编译器。
当请求被处理并且有回复可用时,应该使用获取到的 QDBusMessage
对象来发送回复。在我们的例子中,回复代码可能如下所示
def sendReply(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 del data
如示例所示,当配置了延时回复时,槽的返回值将由 Qt D-Bus 忽略。它们仅用于将适配器描述与远程应用程序通信时确定槽的签名,或者在槽中的代码决定不使用延时回复的情况下使用。
延迟回复本身是通过在原始消息上调用 QDBusMessage::reply() 来从 Qt D-Bus 求得的。然后,调用代码负责最终向调用者发送回复。
警告
当一个调用方发出方法调用来等待回复时,它只会等待有限的时间。如果槽需要花费很长时间来完成,应该在文档中明确这一点,以便调用方可以适当设置更长的超时时间。