如何使用 qdbusxml2cpp 生成同步接口类?

Posted

技术标签:

【中文标题】如何使用 qdbusxml2cpp 生成同步接口类?【英文标题】:How to generate synchronous interface class with qdbusxml2cpp? 【发布时间】:2017-02-05 23:42:07 【问题描述】:

问题总结:qdbusxml2cpp 生成一个QDBusAbstractInterface 子类,其方法异步获取 D-Bus 回复,但我希望它是同步的(即应该阻塞直到收到回复)。

XML 输入:

<?xml version="1.0"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="some.interface.Foo">
    <method name="GetValues">
    <arg name="values" type="a(oasv)" direction="out"/>
        <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;SomeStruct&gt;" />
    </method>
</interface>
</node>

使用此命令会生成一个标头和 .cpp 文件(未显示):

qdbusxml2cpp-qt5 -c InterfaceFoo -p interface_foo  foo.xml

生成的标头:

class InterfaceFoo: public QDBusAbstractInterface

    Q_OBJECT
public:
    static inline const char *staticInterfaceName()
     return "some.interface.Foo"; 

public:
    InterfaceFoo(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);

    ~InterfaceFoo();

public Q_SLOTS: // METHODS
    inline QDBusPendingReply<QList<SomeStruct> > GetValues()
    
        QList<QVariant> argumentList;
        // NOTICE THIS LINE.
        return asyncCallWithArgumentList(QStringLiteral("GetValues"), argumentList);
    

Q_SIGNALS: // SIGNALS
;

namespace some 
namespace interface 
    typedef ::InterfaceFoo Foo;


#endif

如您所见,asyncCallWithArgumentList() 生成的方法是异步的:它预计将 connect()ed 到 D-Bus 回复到达时触发的插槽。

相反,我希望能够做到:

 some::interface::Foo *interface =  new some::interface::Foo("some::interface", "/Foo", QDBusConnection::systemBus(), this);
 // THIS SHOULD block until a reply is received or it times out.
 QList<SomeStruct> data = interface->GetValues();

【问题讨论】:

可能不是您正在寻找的解决方案,但您可以致电interface-&gt;GetValues().value() 阻止直到回复到达 【参考方案1】:

您可以在返回值上使用value() 来阻止,GetValues() 原样:

auto reply = interface->GetValues();
auto data = reply.value<QList<QVariant>>();

唉,生成的界面是为了生成一次,然后成为您的源的一部分。您应该修改它以使用阻塞调用,并添加从变体到具体类型的转换:

inline QDBusPendingReply<QList<SomeStruct>> GetValues()

    QList<QVariant> argumentList;
    auto msg = callWithArgumentList(QDBus::Block, QStringLiteral("GetValues"), argumentList);
    Q_ASSERT(msg.type() == QDBusMessage::ReplyMessage);
    QList<SomeStruct> result;
    for (auto const & arg : msg.arguments())
      result << arg.value<SomeStruct>();
    return result;

最后,您可能希望重新考虑将其设为同步:现实世界是异步的,因此编写代码时好像不是同步的,这往往会适得其反。如果您的代码在主线程中运行并且有一个 gui,那么您将给用户带来糟糕的体验。如果您将代码移动到工作线程,那么您就是在浪费整个线程来支持同步编码风格。即使您正在编写相当于非交互式批处理式实用程序/服务的内容,您也可能会增加延迟,例如不并行发出呼叫。

【讨论】:

非常感谢最后一段的回答和建议。它有帮助! 虽然在生成的源文件/头文件的顶部显示“这是一个自动生成的文件。请勿编辑!对其所做的所有更改都将丢失。”听起来好像不是要修改,而 .xml 是主文件... @Dee 这是你的宇宙,你是它的主人,你制定规则。您使用该工具。这不是上帝的礼物。

以上是关于如何使用 qdbusxml2cpp 生成同步接口类?的主要内容,如果未能解决你的问题,请参考以下文章

qdbus 多个接口在同一个对象路径中

qdbusxml2cpp 无法正常工作

QDBusAbstractAdaptor 对象不导出实现的 dbus 接口

Qt qdbusxml2cpp 没有输出

如何使用 qt-dbus 将错误返回到 dbus?

qdbusxml2cpp 未知类型