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



问题总结: 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(oa{sv})" 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();

您可以在返回值上使用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,你将会给用户带来糟糕的体验。如果将代码移到工作线程中,那么仅仅为了支持同步编码风格就浪费了整个线程。即使你编写的是非交互式批处理风格的实用程序/服务,你也可能会增加延迟,例如,不并行发出调用。

相关内容

  • 没有找到相关文章

最新更新