Instantly share code, notes, and snippets.

Embed
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

This comment has been minimized.

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

@sabhlok2812

This comment has been minimized.

sabhlok2812 commented Dec 14, 2018

what is calculatoradaptor doing ??

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