Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Complete example of D-BUS client and server using Qt5 and CMake.
#include <QDebug>
#include "Calc.hh"
#include <calculatoradaptor.h>
Calc::Calc(QObject *parent)
: QObject(parent)
{
qDebug() << __PRETTY_FUNCTION__;
new ICalculatorAdaptor(this);
QDBusConnection dbus = QDBusConnection::sessionBus();
dbus.registerObject("/my/test/OCalculator", this);
dbus.registerService("my.test.SCalculator");
}
Calc::~Calc() {}
double Calc::multiply(double factor0, double factor1)
{
qDebug() << __PRETTY_FUNCTION__ << factor0 << factor1;
double product = factor0 * factor1;
emit newProduct(product);
return product;
}
double Calc::divide(double dividend, double divisor)
{
qDebug() << __PRETTY_FUNCTION__ << dividend << divisor;
double quotient = dividend / divisor;
emit newQuotient(quotient);
return quotient;
}
#ifndef CALC_HH
#define CALC_HH
#include <QObject>
class Calc : public QObject
{
Q_OBJECT;
Q_CLASSINFO("D-Bus Interface", "my.test.ICalculator");
public:
Calc(QObject *parent);
virtual ~Calc();
public slots:
double multiply(double factor0, double factor2);
double divide(double divident, double divisor);
signals:
void newProduct(double product);
void newQuotient(double quotient);
};
#endif
#include <QCoreApplication>
#include <QtDBus>
#include <QDebug>
int main(int ac, char **av)
{
QCoreApplication a(ac, av);
if (!QDBusConnection::sessionBus().isConnected()) {
qCritical() << "Cannot connect to the D-Bus session bus.\n";
return EXIT_FAILURE;
}
QDBusInterface iface("my.test.SCalculator", "/Calculator", "my.test.ICalculator", QDBusConnection::sessionBus());
if (iface.isValid()) {
QDBusReply<double> reply = iface.call("multiply", 2.0, 3.3);
if (reply.isValid()) {
printf("Reply from multiply was: %e\n", reply.value());
} else {
qCritical() << "Call to multiply failed:" << qPrintable(reply.error().message());
return EXIT_FAILURE;
}
reply = iface.call("divide", 5.2, 0.0);
if (reply.isValid()) {
printf("Reply from divide was: %e\n", reply.value());
return EXIT_SUCCESS;
} else {
qCritical() << "Call to divide failed:" << qPrintable(reply.error().message());
return EXIT_FAILURE;
}
}
qCritical() << "No D-Bus interface found!";
return EXIT_FAILURE;
}
cmake_minimum_required(VERSION 3.5)
project(DBusTest)
find_package(Qt5 CONFIG REQUIRED Core DBus)
set(prog_SRCS my.test.Calculator.xml)
qt5_generate_dbus_interface(Calc.hh
my.test.Calculator.xml
OPTIONS -A
)
qt5_add_dbus_adaptor(prog_SRCS
${CMAKE_CURRENT_BINARY_DIR}/my.test.Calculator.xml
Calc.hh
Calc
)
qt5_wrap_cpp(server_moc Calc.hh)
add_executable(QtDbusServer
${server_moc}
server.cc
Calc.cc
${prog_SRCS}
)
target_include_directories(QtDbusServer
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
target_link_libraries(QtDbusServer
Qt5::DBus
)
add_executable(QtDBusClient
client.cc
)
target_link_libraries(QtDBusClient
Qt5::DBus
)
qt5_wrap_cpp(listener_moc Listen.hh)
add_executable(QtDBusListener
${listener_moc}
listener.cc
Listen.cc
)
target_link_libraries(QtDBusListener
Qt5::DBus
)
#include "Listen.hh"
Listen::Listen(QObject *parent)
: QObject(parent)
{
qDebug() << __PRETTY_FUNCTION__;
}
void Listen::reportNewProduct(double product)
{
qDebug() << "Received a new product " << product;
}
void Listen::reportNewQuotient(double quotient)
{
qDebug() << "Received a new quotient " << quotient;
}
#ifndef LISTEN_HH
#define LISTEN_HH
#include <QtCore>
class Listen : public QObject
{
Q_OBJECT;
public:
Listen(QObject *parent=nullptr);
public slots:
void reportNewProduct(double product);
void reportNewQuotient(double quotient);
};
#endif
#include <QtCore>
#include <QtDBus>
#include "Listen.hh"
int main(int ac, char **av)
{
QCoreApplication a(ac, av);
if(!QDBusConnection::sessionBus().isConnected()) {
qCritical() << "Cannot connect to the D-Bus session bus!";
return EXIT_FAILURE;
}
Listen l;
QDBusConnection::sessionBus().connect(QString(), QString(), "my.test.ICalculator", "newProduct", "d",
&l, SLOT(reportNewProduct(double)));
QDBusConnection::sessionBus().connect(QString(), QString(), "my.test.ICalculator", "newQuotient", "d",
&l, SLOT(reportNewQuotient(double)));
return a.exec();
}
#include <QCoreApplication>
#include "Calc.hh"
int main(int ac, char **av)
{
QCoreApplication a(ac, av);
Calc c(&a);
return a.exec();
}

wincak commented Nov 28, 2017

Thanks for the example, but there seems to be a glitch.

$ ./QtDBusClient 
Call to multiply failed: No such object path '/Calculator'

It can be fixed by replacing
QDBusInterface iface("my.test.SCalculator", "/Calculator", "my.test.ICalculator", QDBusConnection::sessionBus());
with
QDBusInterface iface("my.test.SCalculator", "/my/test/OCalculator", "my.test.ICalculator", QDBusConnection::sessionBus());

But is that how it should be?
Tested with Qt 5.9.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment