DBus-1-TQt  1.0
Providing services over D-Bus

Contents:

Introduction

The TQt3 bindings do not support autogeneration of service objects yet. In order to provide interfaces over D-Bus, an application has to implement the TQT_DBusObjectBase interface and register an instance of the resulting class with the TQT_DBusConnection.

A simple D-Bus client example

#include <dbus/tqdbusconnection.h>;
#include <dbus/tqdbusobject.h>;
class TQStringList;
class TestService : public TQT_DBusObjectBase
{
public:
TestService(const TQT_DBusConnection& connection);
virtual ~TestService();
protected:
virtual bool handleMethodCall(const TQT_DBusMessage& message);
private:
TQT_DBusConnection m_connection;
private:
TQStringList sortStrings(const TQStringList& list);
};
Provides access to a specific D-Bus bus.
A message converts and transports data over D-Bus.
Base interface for D-Bus service objects.
Definition: tqdbusobject.h:303
virtual bool handleMethodCall(const TQT_DBusMessage &message)=0
Method call entry point.
#include <tqstringlist.h>;
#include <dbus/tqdbuserror.h>;
#include <dbus/tqdbusmessage.h>;
TestService::TestService(const TQT_DBusConnection& connection) : m_connection(connection)
{
m_connection.registerObject("/ListSorter", this);
}
TestService::~TestService()
{
m_connection.unregisterObject("/ListSorter");
}
// return false to let D-Bus send a standard error message that the method is unknown
bool TestService::handleMethod(const TQT_DBusMessage& message)
{
if (message.interface() != "org.example.Sort") return false;
if (message.member() == "Strings")
{
// check parameters
if (message.count() != 1 || message[0].type() != TQT_DBusData::List)
{
// method signature not what we expected
"Expected one argument of type array of string");
// send error
m_connection.send(reply);
// tell D-Bus we did handle the call
return true;
}
// call implementation
TQStringList result = sortStrings(message[0].toTQStringList());
// prepare reply
reply << TQT_DBusData::fromList(result);
// send reply
m_connection.send(reply);
// tell D-Bus we did handle the call
return true;
}
return false;
}
TQStringList TestService::sortStrings(const TQStringList& list)
{
TQStringList result = list;
result.sort();
return result;
}
static TQT_DBusData fromList(const TQT_DBusDataList &list)
Creates a data object for the given list.
Definition: tqdbusdata.cpp:637
Class for transporting D-Bus errors.
Definition: tqdbuserror.h:41
static TQT_DBusError stdInvalidArgs(const TQString &message)
Creates a D-Bus standard error for call arguments being invalid.
static TQT_DBusMessage methodError(const TQT_DBusMessage &other, const TQT_DBusError &error)
Creates a message for replying to a D-Bus method call.
TQString interface() const
Returns the message's interface name.
static TQT_DBusMessage methodReply(const TQT_DBusMessage &other)
Creates a message for replying to a D-Bus method call.
TQString member() const
Returns the message's member name.
MessageType type() const
Returns which kind of message this is.
int main(int argc, char** argv)
{
TQApplication app(argc, argv, false);
if (!connection.isConnected())
tqFatal("Cannot connect to session bus");
// try to get a specific service name
if (!connection.requestName("org.example.SortService"))
{
tqWarning("Requesting name 'org.example.SortService' failed. "
"Will only be addressable through unique name '%s'",
connection.uniqueName().local8Bit().data());
}
else
{
tqDebug("Requesting name 'org.example.SortService' successfull");
}
TestService service(connection);
return app.exec();
}
TQString uniqueName() const
Returns the connection identifier assigned at connect.
static TQT_DBusConnection sessionBus()
Gets a connection to the session bus.
bool isConnected() const
Returns whether the connection is connected to a bus.
bool requestName(const TQString &name, int modeFlags=NoReplace)
Requests to be addressable on the bus by a given name.

Requesting service name

When an application connects to D-Bus it gets a unique name generated by the bus daemon.

However, an application providing service will often want to be reachable under a fixed name, like a webserver being reachable through a domain name independent from its actual IP address. See section Service names for details on service names.

In order to get such a specific name an application has to request it using TQT_DBusConnection::requestName()

The example above request "org.example.SortService" but continues with the default unique name in the case some other application is currently owning that name.

Registering objects

To make service objects available to other applications on the same bus the application has to register the objects instances with the connection to the bus using TQT_DBusConnection::registerObject()

Registering means to specify an object path where the object will be located, i.e. how it can be unambiguously be addressed in method calls. See section Object paths for details on object paths.

If the applications has introspectable objects it is recommended to register an introspectable root object, i.e. using "/" as the path, so other applications have a common place to start asking for introspection data.

In the example above a service object providing sorting services on lists is registered on the path "/ListSorter"

Service interfaces

D-Bus methods and signals of a service object a grouped into interfaces.

See section Interface names for details on interface naming.

An object can implement any number of interfaces, for example the interface for the functionality it wants to provide and a D-Bus standard interface like "org.freedesktop.DBus.Introspectable" for providing an XML description of all its interfaces.

The service object of the example above implements just one interface "org.example.Sort" and its handleMethodCall() explicitly checks all received messages and rejects any messsage not sent to this particular interface by returning false and thus telling the D-Bus layer to generate a standard error response.

Multiple interfaces can of course be directly implemented in one C++ class, however it might sometimes be wise to delegate calls for different interfaces to different implementations:

class Interface1 : public TQT_DBusObjectBase
{
public:
Interface1(const TQT_DBusConnection&);
protected:
virtual bool handleMethodCall(const TQT_DBusMessage&);
};
class Interface2 : public TQT_DBusObjectBase
{
public:
Interface2(const TQT_DBusConnection&);
protected:
virtual bool handleMethodCall(const TQT_DBusMessage&);
};
class MultiInterfaceService : public TQT_DBusObjectBase
{
public:
MultiInterfaceService(const TQT_DBusConnection&);
protected:
virtual bool handleMethodCall(const TQT_DBusMessage&);
private:
TQMap<TQString, TQT_DBusObjectBase*> m_interfaces;
};
MultiInterfaceService::MultiInterfaceService(const TQT_DBusConnection& connection)
{
m_interfaces.insert("org.example.Interface1", new Interface1(connection));
m_interfaces.insert("org.example.Interface2", new Interface2(connection));
}
bool MultiInterfaceService::handleMethodCall(const TQT_DBusMessage& message)
{
// delegate call to its interface handler
TQT_DBusObjectBase* handler = m_interfaces[message.interface()];
if (handler != 0)
return delegateMethodCall->(message, handler);
else
return false; // no such interface
}