Qt使用D-Bus几种写法

1. QDBusInterface同步调用

// 必要的头文件
#include <QDBusMessage>
#include <QDBusInterface>
#include <QDBusReply>

// 定义D-Bus的接口
QDBusInterface interface = new QDBusInterface("com.deepin.dde.Launcher", 
                                              "/com/deepin/dde/Launcher", 
                                              "com.deepin.dde.Launcher", 
                                              QDBusConnection::sessionBus());    
// 调用D-Bus接口的方法
QDBusMessage msg = interface->call(QDBus::Block, "IsVisible");
// 查看D-Bus方法的返回值   
QList<QVariant> received = msg.arguments();
// 重载了QDBusReply::operator=,所以下面的写法也是可以的,
// 一个QDBusReply对象是方法调用的应答QDBusMessage对象的一个子集,QDBusReply对象只包含第一个输出参数或错误代码。
// QDBusReply<bool> reply = interface->call(QDBus::Block, "IsVisible");
// qInfo() << reply.value();

2. QDBusInterface异步调用

// 必要的头文件
#include <QDBusPendingReply>
#include <QDBusInterface>
#include <QDBusPendingCallWatcher>

// 定义D-Bus的接口
QDBusInterface interface = new QDBusInterface("com.deepin.dde.Launcher", 
                                              "/com/deepin/dde/Launcher",     
                                              "com.deepin.dde.Launcher", 
                                              QDBusConnection::sessionBus()); 

// 调用D-Bus接口的方法 
QDBusPendingCall pcall = interface->asyncCall("IsVisible");

// 设置等待异步消息的信号槽
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, nullptr);
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &MainWindow::slotDBusCallFinished);

// 处理异步D-Bus消息返回值的槽函数
void MainWindow::slotDBusCallFinished(QDBusPendingCallWatcher *wather)
{
    // 根据消息返回值类型定义QDBusPendingReply
    QDBusPendingReply<bool> reply = *wather;    
    bool isVisable = reply.argumentAt<0>();    
    wather->deleteLater();
    qInfo() << isVisable;
}

3. QDBusMessage发送消息

此方法适用场景为不关心返回值。

// 必要的头文件
#include <QDBusMessage>
#include <QDBusConnection>

// 构造消息体
QDBusMessage msg = QDBusMessage::createMethodCall("com.deepin.dde.Launcher",
                                                  "/com/deepin/dde/Launcher", 
                                                  "com.deepin.dde.Launcher",
                                                  "Show");
// Sends the message over this connection, without waiting for a reply.
// This is suitable for errors, signals,
// and return values as well as calls whose return values are not necessary.
// 发送消息
QDBusConnection::sessionBus().send(msg);

4. QDBusConnection监听信号

需要使用Qt4的SLOT宏将响应信号的槽函数包起来。

// 必要的头文件
#include <QDBusMessage>

QDBusConnection::sessionBus().connect("com.deepin.dde.Launcher", 
                                      "/com/deepin/dde/Launcher",
                                      "com.deepin.dde.Launcher", 
                                      "VisibleChanged", 
                                      this, 
                                      SLOT(slotVisibleChanged(bool)));

如果使用命令行方式测试信号是否能被接收,需要修改上述代码,将D-Bus名称,D-Bus路径,D-Bus接口这些参数全部赋空。

// 必要的头文件
#include <QDBusMessage>

QDBusConnection::sessionBus().connect("", "", "", 
                                      "VisibleChanged", this, SLOT(slotVisibleChanged(bool)));

对应的测试命令如下。

dbus-send --session --type=signal /com/deepin/dde/Launcher com.deepin.dde.Launcher.VisibleChanged boolean:false

参考文档

5. QDBusConnection注册服务

因为用到了Qt的MOC机制,所以下面的类定义一定要放在头文件中(也可以手动执行moc命令生成moc_xxx.cpp文件)。否则会有undefined reference to vtable的错误。

class DBusDemo: public QObject
{
    Q_OBJECT
    // 定义D-Bus服务名称
    Q_CLASSINFO("D-Bus Interface", "org.example.QDBusDemo")
    // 申明属性
    Q_PROPERTY(QString nickname READ nickname WRITE setNickname MEMBER myNickname)

public:
    explicit DBusDemo(QObject *parent = nullptr): QObject(parent) {}
    // 属性-读
    QString nickname() { return myNickname; }
    // 属性-写
    void setNickname(QString name){ myNickname = name; }

public slots:
    // D-Bus方法
    QDBusVariant helloJerry(const QString &name) { return QDBusVariant("Hello " + name); }

signals:
    // D-Bus信号
    void sayHello();

private:
    QString myNickname = "Jerry";
};

通过D-Bus实现单例模式。

DBusDemo dbusDemo;
QDBusConnection dbus = QDBusConnection::sessionBus();  
// 尝试注册D-Bus服务,如果注册成功,表示应用没有启动,启动应用。
// 如果注册失败,则说明应用已经启动了,调用接口,让已启动的应用去完成任务。  
if (dbus.registerService("org.example.QDBusDemo")) {        
    dbus.registerObject("/org/example/QDBusDemo", 
                        &dbusDemo, 
                        QDBusConnection::ExportAllSlots 
                        | QDBusConnection::ExportAllProperties 
                        | QDBusConnection::ExportAllSignals);
    // TODO 启动APP等逻辑
} else {        
    // TODO 通过上述D-Bus方法调用本服务的接口完成业务逻辑
}

6. QDBusAbstractAdaptor

简单使用,参考上述用法即可,深度使用D-Bus,可使用该模式。
参考Qt的官方例子,D-Bus Complex Ping Pong Example,自行百度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值