警告

本节包含自动从C++转换为Python的代码片段,可能包含错误。

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

D-Bus适配器中的槽与常规、公共槽一样声明,但它们的参数必须遵循某些规则(更多信息请参阅Qt D-Bus类型系统)。不符合这些规则的槽或非公共槽无法通过D-Bus访问。

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

槽可以是三种类型之一

  1. 异步

  2. 输入唯一

  3. 输入和输出

异步槽#

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

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

异步槽在方法签名中使用关键字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 求得的。然后,调用代码负责最终向调用者发送回复。

警告

当一个调用方发出方法调用来等待回复时,它只会等待有限的时间。如果槽需要花费很长时间来完成,应该在文档中明确这一点,以便调用方可以适当设置更长的超时时间。