QDBus学习分享。

85 篇文章 1 订阅

使用到QDBus一般就是用于进程通信。QT进程通信的几大方法中,QDBus可以实现不同进程间信号槽的连接,而其它几中方法QSharedMemory(共享内存),QProcess(进程),QLocalSocket(本地通信),QTcpSocket(tcp通信)中都无法做到这点,至于详细原因,这里不做细讲。

使用QDBus,常用的几个类,分别是QDBusMessage(用于消息发送)、QDBusInterface(用于消息发送)、QDBusConnection(用于连接、注册、发送)。

在通信时会通过总线来进行,这里支持系统总线和回话总线。
//system bus(系统总线),用于系统(Linux)和用户程序之间进行通信和消息的传递;
//session bus(回话总线),用于桌面(GNOME, KDE等)用户程序之间进行通信。

服务器流程:1、获取连接。2、通过连接注册服务器名。3、通过连接注册服务器对象路径。4、根据需要连接客户端的槽函数。5、发送消息。
直接上代码,注释中已经全部说明了。
#include "mainwindow.h"
#include <QApplication>
#include <QDBusConnection>
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //system bus(系统总线),用于系统(Linux)和用户程序之间进行通信和消息的传递;
    //session bus(回话总线),用于桌面(GNOME, KDE等)用户程序之间进行通信。
    QDBusConnection dbus = QDBusConnection::sessionBus();
    // 服务器名:com.widget.test
    if(!dbus.registerService("com.mydbus.server"))
    {
        QMessageBox::information(0,"error","dbus registerservice fail");
        return -1;
    }

    MainWindow w;
    /* 服务器对象路径:/test/objects
      QDBusConnection::RegisterOption::ExportAllSlots 对应的所有操函数必须为public权限
     */
    dbus.registerObject("/test/objects",&w,QDBusConnection::RegisterOption::ExportAllSlots);

    w.show();

    return a.exec();
}

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtWidgets>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusInterface>

class MainWindow : public QMainWindow
{
    Q_OBJECT

    // DBus固定字段 D-Bus Interface
    // 服务器接口:com.service.interface,
    Q_CLASSINFO("D-Bus Interface","com.service.interface")
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
public slots:
    int showmin();
    int shownormal();
    void slotsend(bool flag);
private slots:
    void service_get(QString name, int num);
private:
    QPushButton* m_sendbtn;
    QTextEdit* m_readedit;
    QLineEdit* m_sendedit;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "mainwindow.h"
#include <QApplication>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(300,300);
    this->setWindowTitle("mydbus server");
    QVBoxLayout* lay = new QVBoxLayout(this);
    m_sendbtn = new QPushButton("发送",this);
    m_sendedit = new QLineEdit(this);
    m_readedit = new QTextEdit(this);
    lay->addWidget(m_sendedit);
    lay->addWidget(m_sendbtn);
    lay->addWidget(m_readedit);
    QWidget* w = new QWidget(this);
    this->setCentralWidget(w);
    w->setLayout(lay);

    connect(m_sendbtn,SIGNAL(clicked(bool)),this,SLOT(slotsend(bool)));
    /*
     * 服务器名:null
     * 服务器临时路径:/home/yjd/testpath
     * 服务器临时接口:com.interface
     * 自定义的信号:send_to_server
     */
    QDBusConnection::sessionBus().connect("","/home/yjd/testpath","com.interface","send_to_server",this,SLOT(service_get(QString,int)));
}

MainWindow::~MainWindow()
{

}

void MainWindow::service_get(QString name,int num)
{
    m_readedit->append(QString("接收:%1-%2").arg(name).arg(num));
}

void MainWindow::slotsend(bool flag)
{
    /*
     * 服务器临时路径:/home/yjd/testpath
     * 服务器临时接口:com.interface
     * 自定义的信号:send_to_server
     */
    QDBusMessage msg = QDBusMessage::createSignal("/home/yjd/testpath","com.interface","send_to_control");
    msg<<m_sendedit->text()<<888;
    QDBusConnection::sessionBus().send(msg);
    m_readedit->append(QString("参数:%1 发送:%2").arg(flag).arg(m_sendedit->text()));
}

int MainWindow::showmin()
{
    showMinimized();
    m_readedit->append("最小化");
    return 2021;
}

int MainWindow::shownormal()
{
    showNormal();
    hide();
    show();
    m_readedit->append("恢复正常");
    return 2020;
}

客户端流程:1、根据需要链接槽函数。2、发送信号。3、根据需要也可以发送服务端注册的槽函数。

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtWidgets>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusInterface>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
    void control(QString method);
private slots:
    void service_get(QString name, int num);
    void slotsend();
    void slotnormal();
    void slotmin();
    void slottest();
private:
    QPushButton* m_sendbtn;
    QPushButton* m_minbtn;
    QPushButton* m_normalbtn;
    QPushButton* m_testbtn;
    QTextEdit* m_readedit;
    QLineEdit* m_sendedit;
};

#endif // WIDGET_H

#include "widget.h"
#include <QApplication>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(300,400);
    this->setWindowTitle("mydbus-control");
    QVBoxLayout* lay = new QVBoxLayout(this);
    m_sendbtn = new QPushButton("发送",this);
    m_minbtn = new QPushButton("最小化",this);
    m_normalbtn = new QPushButton("正常",this);
    m_testbtn = new QPushButton("测试",this);

    m_sendedit = new QLineEdit(this);
    m_readedit = new QTextEdit(this);
    lay->addWidget(m_minbtn);
    lay->addWidget(m_normalbtn);
    lay->addWidget(m_testbtn);
    lay->addWidget(m_sendedit);
    lay->addWidget(m_sendbtn);
    lay->addWidget(m_readedit);
    this->setLayout(lay);

    connect(m_minbtn,SIGNAL(clicked()),this,SLOT(slotmin()));
    connect(m_normalbtn,SIGNAL(clicked()),this,SLOT(slotnormal()));
    connect(m_testbtn,SIGNAL(clicked()),this,SLOT(slottest()));
    connect(m_sendbtn,SIGNAL(clicked()),this,SLOT(slotsend()));
    /*
     * 服务器名:null
     * 服务器临时路径:/home/yjd/testpath
     * 服务器临时接口:com.interface
     * 自定义的信号:send_to_server
     */
    QDBusConnection::sessionBus().connect("","/home/yjd/testpath","com.interface","send_to_control",this,SLOT(service_get(QString,int)));
}

Widget::~Widget()
{

}

void Widget::service_get(QString name,int num)
{
    m_readedit->append(QString("接收:%1-%2").arg(name).arg(num));
}

void Widget::slotsend()
{
    /*
     * 服务器临时路径:/home/yjd/testpath
     * 服务器临时接口:com.interface
     * 自定义的信号:send_to_server
     */
    QDBusMessage msg = QDBusMessage::createSignal("/home/yjd/testpath","com.interface","send_to_server");
    msg<<m_sendedit->text()<<666;
    QDBusConnection::sessionBus().send(msg);
    m_readedit->append(QString("发送:%1").arg(m_sendedit->text()));
}

void Widget::slotmin()
{
    control("showmin");   //名称必须与服务端的槽函数名称一样
}

void Widget::slotnormal()
{
    control("shownormal");  //名称必须与服务端的槽函数名称一样
}

void Widget::slottest()
{
    control("slotsend"); //名称必须与服务端的槽函数名称一样
}

void Widget::control(QString method)
{
    bool flag = true;
    /* 
     * 注册的服务器名称:com.widget.test
     * 注册的服务器对象路径:/test/objects
     * 注册的服务器接口:com.service.interface,
     * 方法名称为:method
     */
#if 1
    //方法一 绑定方法和服务端注册的相关接口
    QDBusMessage msg = QDBusMessage::createMethodCall("com.mydbus.server","/test/objects","com.service.interface",method);
    if (method == "slotsend")
        msg<<flag;    //有参数时,添加参数
    QDBusMessage res = QDBusConnection::sessionBus().call(msg);  //发送个服务端
#else
    //方法二 在接口interface中设置服务端注册的相关接口,然后接口绑定方法。
    QDBusInterface interface("com.mydbus.server","/test/objects","com.service.interface",QDBusConnection::sessionBus());
    if (!interface.isValid())
    {
        QMessageBox::information(this,"error","dbus interface fail");
        return;
    }
    QDBusMessage res;
    if (method == "slotsend")
        res = interface.call(method,flag); // 有参数
    else
        res = interface.call(method); // 无参数

#endif
    if (res.type() == QDBusMessage::ReplyMessage)
    {
        //从返回参数获取返回值
        if (res.arguments().size() > 0)
        {
            int value = res.arguments().takeFirst().toInt();
            m_readedit->append(QString("%1 返回值:%2").arg(method).arg(value));
        }
        else
            m_readedit->append(QString("%1 返回值:null").arg(method));

    }
    else
    {
        m_readedit->append(QString("%1 返回值失败").arg(method));
    }
}

在这里插入图片描述

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值