警告

本节包含从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请求的。然后,调用代码有责任最终向调用者发送回复。

警告

当调用者放置一个方法调用并等待回复时,它只会等待有限的时间。预计需要很长时间才能完成的插槽应在文档中明确说明这一点,以便调用者正确设置更高的超时时间。