Contents:
While it is of course possible to just exchange D-Bus messages with a D-Bus service, it is a lot more comfortable to use QDBusProxy.
With QDBusProxy you only need to specify the service object once, i.e. its D-Bus name, path and interface, and just provide the method and its parameters when initiating an invokation.
Additionally the proxy transforms D-Bus signals from the proxy's peer (the D-Bus service object's interface it is associated with) to QObject signal carrying the original signal's content.
#include <dbus/qdbusconnection.h> #include <dbus/qdbusmessage.h> #include <dbus/qdbusproxy.h> int main() { // establish a connection to the session bus QDBusConnection connection = QDBusConnection::sessionBus(); if (!connection.isConnected()) qFatal("Failed to connect to session bus"); // create a proxy object for method calls QDBusProxy proxy(connection); proxy.setService("org.freedesktop.DBus"); // who we work with proxy.setPath("/org/freedesktop/DBus"); // which object inside the peer work with proxy.setInterface("org.freedesktop.DBus"); // which of its interfaces we will use // call the "ListNames" method. It returns an array of string, in Qt3 terms // a QStringList, it expects no parameters QValueList<QDBusData> params; QDBusMessage reply = proxy.sendWithReply("ListNames", params); if (reply.type() != QDBusMessage::ReplyMessage) qFatal("Call failed"); if (reply.count() != 1 || reply[0].type() != QDBusData::List) qFatal("Unexpected reply"); bool ok = false; QStringList names = reply[0].toQStringList(&ok); if (!ok) qFatal("Unexpected reply"); for (QStringList::iterator it = names.begin(); it != names.end(); ++it) { qDebug("%s", (*it).local8Bit().data()); } return 0; }
A connection to the bus is acquired using QDBusConnection::sessionBus()
Next, a proxy is created for the object "/org/freedesktop/DBus"
with interface "org.freedesktop.DBus"
on the service "org.freedesktop.DBus"
This is a proxy for the message bus itself.
There are two choices for method invocation:
As seen in the example code above, a synchronous method call can be achieved by QDBusProxy::sendWithReply(). It sends a method call to the remote object, and blocks until reply is received. The outgoing arguments are specified as a list of QDBusData.
To invoke a method asynchronously, connect the proxy's signal QDBusProxy::asyncReply(int, const QDBusMessage&) to a suitable slot like with any other Qt Signal-Slot connection.
Then call QDBusProxy::sendWithAsyncReply() It returns a numerical identifier of the call, so it can be related in the slot once the result is available.
The slot's first argument is the reveived reply's call identifier as returned by the method call. The second parameter is the reply message similar to the one in the synchronous call.
To receive D-BUS signals just connect to the QDBusProxy's signal QDBusProxy::dbusSignal(const QDBusMessage&)
It will be emitted whenever a D-Bus signal message is received from the peer object. Filtering of signals is based on the value set for service
, path
and interface
service
will only happen if service
is a unique D-Bus name, i.e. if it starts with a colon ":"
since D-Bus signals carry the sender's unique name and filtering by a requested name would reject all signalsUsually a proxy will be also be used to send to the peer object, thus having them all set. However if a proxy is only needed for signals, any of the three properties can be omitted (e.g. set to QString::null
), in which case only the available properties will be checked against the respective message field when deciding about dropping or emitting the message. See QDBusProxy::handleDBusSignal()
If you want all signal travelling on the bus, or apply filtering for different criteria, e.g. get all signals coming from interfaces starting with "org."
, use QDBusConnection::connect()
instead. The signature of the slot stays the same.
First declare a receiver class:
class MyReceiver : public QObject { Q_OBJECT public slots: void handleDBusSignal(const QDBusMessage&); };
Then somewhere else in a source file:
QDBusConnection connection = QDBusConnection::sessionBus(); MyReceiver* receiver1 = new MyReceiver(); connection.connect(receiver1, SLOT(handleDBusSignal(const QDBusMessage&)));
receiver1
will get all signals on this connection
QDBusProxy* proxy = new QDBusProxy(connection); proxy->setService("org.freedesktop.DBus"); // who we work with proxy->setPath("/org/freedesktop/DBus"); // which object inside the peer work with proxy->setInterface("org.freedesktop.DBus"); // which of its interfaces we will use MyReceiver* receiver2 = new MyReceiver(); QObject::connect(proxy, SIGNAL(dbusSignal(const QDBusMessage&)), receiver2, SLOT(handleDBusSignal(const QDBusMessage&)));
receiver2
will only get signals coming from the proxy's peer interface