一、简介

  • QtDBus是一个使用D-Bus协议进行进程间通信的仅在Unix运行的库,是对D-Bus底层API的封装实现。
  • QtDBus模块提供了使用Qt信号槽机制扩展的接口。
  • 要使用QtDBus模块,需要在pro工程文件中增加下列代码来链接QtDBus库:
QT += qdbus

二、使用-收发消息

  • 1、使用QDBusMessage发消息
  • 发送代码:
QDBusMessage message =QDBusMessage::createSignal("/path", "com.message.test", "send_to_service");
    message << "发送内容";
    QDBusConnection::sessionBus().send(message);
  • creatSignal中:
  • ①"/path":对象路径
  • ②"com.message.test":接口名称
  • ③"send_to_service":方法名
  • 这三个参数和下面QDBusConnection::sessionBus().connect()中参数对应
  • 2 接收QDBusMessage发送的消息:
  • 接收代码:
  • 2.1 建立到session bus的连接:
QDBusConnection::sessionBus().connect(QString(), "/path", "com.message.test", "send_to_service",
 									 this, SLOT(service_get(QString)));
  • 2.2 接收消息处理:
void Widget::service_get(QString str)
{
    ui->textBrowser->append(QString("接收消息:%1").arg(str));
}
  • QDBusConnection::sessionBus().connect()中:
  • ①QString():服务名,这里为空
  • ②"/path":对象路径
  • ③"com.message.test":接口名称
  • ④"send_to_service":方法名
  • ⑤this:接受者
  • ⑥service_get(QString):槽函数
  • 这几个参数和上面creatSignal中参数对应

三、使用-方法调用

  • 1 server端在总线申请服务,供客户端调用
  • 1.1 首先要在相应类中定义接口名称,com.widget.test.show为接口名称
Q_OBJECT
	//定义Interface名称为com.widget.test.show
    Q_CLASSINFO("D-Bus Interface", "com.widget.test.show")
  • 1.2 然后要将方法放在public slots下
public slots:
    int showmin();
    int showmax();
    int shownormal();
    int hideclose();
  • 1.3 最后建立到session bus的连接
//建立到session bus的连接
    QDBusConnection connection = QDBusConnection::sessionBus();
    //在session bus上注册名为com.widget.test的服务
    if(!connection.registerService("com.widget.test"))
    {
        qDebug() << "error:" << connection.lastError().message();
        exit(-1);
    }
    Widget w;//申请方法所在的类
    //注册名为/test/objects的对象,把类Object所有槽函数导出为object的method
    connection.registerObject("/test/objects", &w,QDBusConnection::ExportAllSlots);
    w.show();
  • 2 客户端调用服务方法
QDBusMessage message = QDBusMessage::createMethodCall("com.widget.test",
                           "/test/objects",
                           "com.widget.test.show",
                           method);
    //发送消息
    QDBusMessage res = QDBusConnection::sessionBus().call(message);
    //判断method是否被正确返回
    if (res.type() == QDBusMessage::ReplyMessage)
    {
        //从返回参数获取返回值
        int value = res.arguments().takeFirst().toInt();
        ui->textBrowser->append(QString("%1 返回值:%2").arg(method).arg(value));
    }
    else
    {
         ui->textBrowser->append(QString("%1  method called failed!").arg(str));
    }
  • ①服务名称为:com.widget.test
  • ②对象路径为:/test/objects
  • ③接口名称为:om.widget.test.show
  • ④方法名称为:method
  • 这里与上面server端建立的相关信息相对应

四、案例效果

qdbus服务端注册session bus_qt

五、关键代码

  • 服务端
  • widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

    //定义Interface名称为com.widget.test.show
    Q_CLASSINFO("D-Bus Interface", "com.widget.test.show")
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    int showmin();
    int showmax();
    int shownormal();
    int hideclose();
private slots:
    void on_pushButton_clicked();
    void service_get(QString);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
  • widget.cpp
#include "widget.h"
#include "ui_widget.h"

#include <QDBusMessage>
#include <QDBusConnection>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("QDBus-server");
    move(100,100);
    this->setWindowFlags(Qt::WindowStaysOnTopHint);


    /* QDBusConnection::sessionBus().connect()  建立到session bus的连接,触发 service_get函数
     * 参数1:                  服务名称,这里为空
     * 参数2:"/cpath"     对象路径
     * 参数3:"com.message.test"  接口名称
     * 参数4:"send_to_service" 方法名
     * 参数5:this              消息接收者
     */
    QDBusConnection::sessionBus().connect(QString(), "/path", "com.message.test", "send_to_service", 
    this, SLOT(service_get(QString)));

}

void Widget::on_pushButton_clicked()
{
    /* "/path" :      对象路径
     * "com.message.test" :   接口名称
     * "send_to_control" :  方法名
     * 这里参数和接收的地方 QDBusConnection::sessionBus().connect()参数对应
     */
    QDBusMessage message =QDBusMessage::createSignal("/path", "com.message.test", "send_to_control");
    message << ui->lineEdit->text();
    QDBusConnection::sessionBus().send(message);
    ui->textBrowser->append(QString("发送消息:%1").arg(ui->lineEdit->text()));
}

int Widget::showmin()
{
    showMinimized();
    ui->textBrowser->append("showmin 此方法被调用");
    return 1;
}

int Widget::showmax()
{
    showMaximized();
    hide();
    show();
    ui->textBrowser->append("showmax 此方法被调用");
    return 2;
}

int Widget::shownormal()
{
    showNormal();
    hide();
    show();
    ui->textBrowser->append("shownormal 此方法被调用");
    return 3;
}

int Widget::hideclose()
{
    close();
    ui->textBrowser->append("hideclose 此方法被调用");
    return 4;
}

void Widget::service_get(QString str)
{
    ui->textBrowser->append(QString("接收消息:%1").arg(str));
}

Widget::~Widget()
{
    delete ui;
}
  • main.cpp
#include "widget.h"
#include <QApplication>
#include <QDBusConnection>
#include <QDebug>
#include <QDBusError>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //建立到session bus的连接
    QDBusConnection connection = QDBusConnection::sessionBus();
    //在session bus上注册名为com.widget.test的服务
    if(!connection.registerService("com.widget.test"))
    {
        qDebug() << "error:" << connection.lastError().message();
        exit(-1);
    }

    Widget w;
    //注册名为/test/objects的对象,把类Object所有槽函数导出为object的method
    connection.registerObject("/test/objects", &w,QDBusConnection::ExportAllSlots);
    w.show();
    return a.exec();
}
  • 客户端
  • widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private slots:
    void on_pushButton_5_clicked();
    void service_get(QString);

private:
    void control(QString str);
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::WindowStaysOnTopHint);
    this->setWindowTitle("QDBus-control");

    connect(ui->pushButton,&QPushButton::clicked,this,[=](){
        control("hideclose");
    });
    connect(ui->pushButton_2,&QPushButton::clicked,this,[=](){
        control("showmin");
    });
    connect(ui->pushButton_3,&QPushButton::clicked,this,[=](){
        control("shownormal");
    });
    connect(ui->pushButton_4,&QPushButton::clicked,this,[=](){
        control("showmax");
    });

    /* QDBusConnection::sessionBus().connect()  建立到session bus的连接,触发 service_get函数
     * 参数1:                  服务名称,这里为空
     * 参数2:"/path"     对象路径
     * 参数3:"com.message.test"  接口名称
     * 参数4:"send_to_service" 方法名
     * 参数5:this              消息接收者
     */
    QDBusConnection::sessionBus().connect(QString(), "/path", "com.message.test", "send_to_control", 
    this, SLOT(service_get(QString)));
}

void Widget::control(QString method)
{
    /* 造一个method_call消息
     * 服务名称为:com.widget.test
     * 对象路径为:/test/objects
     * 接口名称为:om.widget.test.show,
     * 方法名称为:method
     */
    QDBusMessage message = QDBusMessage::createMethodCall("com.widget.test",
                           "/test/objects",
                           "com.widget.test.show",
                           method);
    //发送消息
    QDBusMessage res = QDBusConnection::sessionBus().call(message);
    //判断method是否被正确返回
    if (res.type() == QDBusMessage::ReplyMessage)
    {
        //从返回参数获取返回值
        int value = res.arguments().takeFirst().toInt();
        ui->textBrowser->append(QString("%1 返回值:%2").arg(method).arg(value));
    }
    else
    {
         ui->textBrowser->append(QString("%1  method called failed!").arg(method));
    }
}

void Widget::service_get(QString str)
{
    ui->textBrowser->append(QString("接收消息:%1").arg(str));
}

void Widget::on_pushButton_5_clicked()
{
    /* "/path" :      对象路径
     * "com.message.test" :   接口名称
     * "send_to_control" :  方法名
     * 这里参数和接收的地方 QDBusConnection::sessionBus().connect()参数对应
     */
    QDBusMessage message =QDBusMessage::createSignal("/path", "com.message.test", "send_to_service");
    message << ui->lineEdit->text();
    QDBusConnection::sessionBus().send(message);
    ui->textBrowser->append(QString("发送消息:%1").arg(ui->lineEdit->text()));
}

Widget::~Widget()
{
    delete ui;
}
  • main.cpp
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}