The wonderful world of DBUS

Time:2022-6-16

Story background

In Linux development, we often use DBUS for interprocess communication, but how to understand DBUS server and client? Many friends may encounter similar problems, and they are vague. Next, we will serve hard dishes directly.

The road of exploration

  1. First of all, understand what DBUS is and what role it plays?
  2. How to make your own program into a DBUS service?
  3. How to call the DBUS interface?

Experience

The basic concept is not introduced here. You can find it on the Internet by yourself. There are many materials. I will share my problems and some experiences with you.

I DBUS server

  1. xxx. What needs to be prepared for the H header file
class Test : public QObject, protected QDBusContext
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "com.test")

public slots:
	void slot1();
signals:
	void signal1();
}
  1. Generate the corresponding XML file according to the header file
qdbuscpp2xml -A test.h -o com.test.xml
  1. The adapter class is generated according to XML generation. Here is how to write cmake
qt5_add_dbus_adaptor(
    test_SRCS
    ${CMAKE_CURRENT_SOURCE_DIR}/com.test.xml
    test.h
    Test
)
  1. Contents prepared by main function
#include "testadaptor.h"

#define Service "com.test"
#define Path "/com/test"
#define Interface "com.test"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Test test;
    TestAdaptor adapter(&test);
    Q_UNUSED(adapter);
    if (!QDBusConnection::sessionBus().registerService(Service)) {
        return -1;
    }
    if (!QDBusConnection::sessionBus().registerObject(Path, Interface, &watermark)) {
        return -2;
    }
    return app.exec();
}

So far, all the preparations related to the DBUS server have been completed. If you want others to pull up the DBUS service when calling your DBUS interface, you should also make the following preparations:

  • Prepare test Service file
[Unit]
Description=xxx
[Service]
Type=simple
ExecStart=/usr/bin/test
Restart=always
RestartSec=1
[Install]
WantedBy=default.target
  • test. Service file installation location /share/dbus-1/services, where we directly write to cmake
install_files(
    "/share/dbus-1/services"
    FILES
    ${CMAKE_CURRENT_BINARY_DIR}/com.deepin.watermark.service
)

II Client calls DBUS interface

  1. Monitoring signal
QDBusConnection::sessionBus().connect("servername", "path", "interface", "signal", this, SLOT(xxx()));
  1. Calling methods and properties
QDBusInterface screensaverInterface("servername", "path", "interface");
screensaverInterface. property("isRunning"). toBool();// Get attribute value
QDBusReply reply = screensaverInterface. call("method");// Call method
  1. Monitoring attribute signal change
QDBusConnection::sessionBus().connect("servername", "path", "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(displayProperty(QString, QVariantMap, QStringList)));

reference material

QT advanced – D-Bus quick start 1
QT advanced – D-Bus quick start 2