警告
本节包含从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请求的。然后,调用代码有责任最终向调用者发送回复。
警告
当调用者放置一个方法调用并等待回复时,它只会等待有限的时间。预计需要很长时间才能完成的插槽应在文档中明确说明这一点,以便调用者正确设置更高的超时时间。