Once more with the dbus/C++ wrapper talk...
Rick L Vinyard Jr
rvinyard at cs.nmsu.edu
Sun Jan 28 12:27:22 PST 2007
I have a pair of libraries (one C++, the other C++/gtkmm based), and
need to add a dbus interface to many of the objects in the library.
So, I was faced with the two options of:
(1) using the C bindings
(2) using one of the multitude of C++ binding proposals
The former option just wasn't where I wanted to go. Why? I'm lazy. It's
just too much work to integrate the C bindings into my code.
So, looking to the latter option I've been examining the following
attempts: (not to snub the QT dbus bindings, but I didn't examine them
as a candidate for a library that depends on gtkmm)
Eugene Zilberstein's Libdbus++
Murray Cumming's dbus-cpp and dbusmm
Paolo Durante's dbus-c++ and cbus
Of the five, only dbus-c++ is actively developed and seems to evolved to
address many of the issues voiced over the design of dbus C++ wrappers.
However, there are some aspects of dbus-c++ that I have issues with with
respect to completeness or with design.
Despite some reservations, I think dbus-c++ is an excellent start toward
developing a dbus-cxx binding (I saw there was some preference for
dbus-cxx over dbus-cpp). I would really like to see dbus-c++ moved from
the OpenWengo development and a concerted effort begin on
freedesktop.org... or sourceforge... or wherever to arrive at a set of
dbus C++ bindings that consolidate the various efforts with a focus on
two libraries (and yes, I'm not just asking for someone to do it, I'm
offering to help...):
(1) dbus-cxx with no dependency on glibmm
(2) dbus-glibmm-cxx with a dependency on glibmm
I would suggest this approach for several reasons:
* dbus-c++ has already demonstrated an approach that satisfies (1)
* dbus-c++ appears to allow the creation of (2) through the virtual
methods of the Dispatcher class
* It's similar to the approach Murray was taking with dbus-cpp and
Several other thoughts on dbus-c++...
I think the project directory structure needs to be massaged a bit...
i.e. move the headers and source into one directory called dbus-cxx, and
use automake's library_includedir to put the files into the right place.
It would probably be better to rename the generated server side glue
files from <interface>-glue.h to <interface>-server-glue.h or something
to indicate that it is a generated server-side stub because of the next
I would like to see dbusxx-xml2cpp have the ability to generate a client
side stub. The point of this is to simplify client side development. Not
only could C++ libraries ship their client side stubs, it would make it
possible to ship a generated library of C++ client side stubs for an
non-C++ server side implementation as well as simplifying client side
stubs for apps.
As a specific example, I'll use the hal-listen code from dbus-c++ which
relies on the HAL dbus interface:
hal-listen defines two client side dbus proxy classes, HalDeviceProxy
and HalManagerProxy. Looking to the HalManagerProxy specifically... it
looks like this:
I started to paste the code in, but substituted the links because it was
way too long... and that's precisely what my point will be.
Given the following introspection specification (see 1: below for notes
and problems on generation) in HalManager-introspect.xml:
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object
<arg name="devices" direction="out" type="ao"/>
<arg name="udi" type="s"/>
<arg name="udi" type="s"/>
dbuscxx-xml2cpp could generate a client stub that would take one of two
approaches (well, at least only two that I can think of) for the
DeviceAdded and DeviceRemoved signals:
(1) Instead of attaching to the DeviceAddedCb, the stub would have the
following method in the public interface (which means adding sigc++ to
sigc::signal<void,const DBus::String&> signal_DeviceAdded()
(2) Or, define a method such as:
virtual void on_DeviceAdded( const DBus::String& udi );
The client stub would also add one of the following methods:
(1) std::vector<DBus::Path> GetAllDevices();
or without using std::tr1::tuple (since it is possible to have multiple
return values, they would have to be handled somehow):
(2) void GetAllDevices(std::vector<DBus::Path>& devices);
Additionally, the generated stub would need a constructor that looks
HalManagerProxy(const Path& path, const char* service);
The interface name was specifically left off, since that can be inferred
from the introspection XML.
Assuming the second option on each of the above approaches, this would
simplify the hal-listen HalManagerProxy to look something like:
class MyHalManagerProxy: public HalManagerProxy
virtual void on_DeviceAdded(const DBus::String& udi);
virtual void on_DeviceRemoved(const DBus::String& udi);
std::map< DBus::String, DBus::RefPtr< HalDeviceProxy > > _devices;
std::vector< DBus::Path > udis;
std::vector< DBus::String >::iterator it;
for(it = udis.begin(); it != udis.end(); ++it)
std::cout << "found device " << *it << std::endl;
_devices[*it] = new HalDeviceProxy(this->connection(), *it);
void MyHalManagerProxy::on_DeviceAdded( const DBus::String& udi )
_devices[udi] = new HalDeviceProxy(this->connection(), udi);
std::cout << "added device " << udi << std::endl;
void MyHalManagerProxy::on_DeviceRemoved( const DBus::String& udi )
std::cout << "removed device " << udi << std::endl;
Anyway, anyone interested???
1: The introspection was generated in python via:
>>> import dbus
u'<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object
<interface name="org.freedesktop.DBus.Introspectable">\n <method
name="Introspect">\n <arg name="data" direction="out"
</interface>\n <interface name="org.freedesktop.Hal.Manager">\n
<method name="GetAllDevices">\n <arg name="devices" direction="out"
</method>\n <method name="DeviceExists">\n <arg
name="does_it_exist" direction="out" type="b"/>\n <arg name="udi"
</method>\n <method name="FindDeviceStringMatch">\n <arg
name="devices" direction="out" type="ao"/>\n <arg name="key"
<arg name="value" direction="in" type="s"/>\n </method>\n
<method name="FindDeviceByCapability">\n <arg name="devices"
<arg name="capability" direction="in" type="s"/>\n </method>\n
<method name="NewDevice">\n <arg name="temporary_udi"
</method>\n <method name="Remove">\n <arg name="udi"
direction="in" type="s"/>\n </method>\n <method
<arg name="temporary_udi" direction="in" type="s"/>\n <arg
name="global_udi" direction="in" type="s"/>\n </method>\n
and has the following changes:
* I removed the Introspection interface
* I removed the methods that don't pertain to the example
* I manually added the signals since they weren't reported in
More information about the dbus