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++
     http://svn.berlios.de/viewcvs/bluetool/trunk/lib/cbus/

     Murray Cumming's dbus-cpp and dbusmm
     http://www.freedesktop.org/wiki/Software_2fdbus_2dcpp
     http://webcvs.freedesktop.org/dbus/dbusmm/

     Paolo Durante's dbus-c++ and cbus
     
http://dev.openwengo.org/trac/openwengo/trac.cgi/browser/wengophone-ng/branches/wengophone-dbus-api/libs/dbus
     http://svn.berlios.de/viewcvs/bluetool/trunk/lib/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) 
above
     * 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 
dbusmm

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 
item below.

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:
    
http://dev.openwengo.org/trac/openwengo/trac.cgi/browser/wengophone-ng/branches/wengophone-dbus-api/libs/dbus/examples/hal/hal-listen.h
    
http://dev.openwengo.org/trac/openwengo/trac.cgi/browser/wengophone-ng/branches/wengophone-dbus-api/libs/dbus/examples/hal/hal-listen.cpp

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 
Introspection 
1.0//EN"\n"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
    <node>
      <interface name="org.freedesktop.Hal.Manager">
        <method name="GetAllDevices">
          <arg name="devices" direction="out" type="ao"/>
        </method>
        <signal name="DeviceAdded">
          <arg name="udi" type="s"/>
        </signal>
        <signal name="DeviceRemoved">
          <arg name="udi" type="s"/>
        </signal>
      </interface>
    </node>

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 
the dependencies):
          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 
something like:
       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
    {
    public:
        MyHalManagerProxy( );
    private:
       virtual void on_DeviceAdded(const DBus::String& udi);
       virtual void on_DeviceRemoved(const DBus::String& udi);
        std::map< DBus::String, DBus::RefPtr< HalDeviceProxy > > _devices;
    };

    MyHalManagerProxy::MyHalManagerProxy( ):
        HalManagerProxy("/org/freedesktop/Hal/Manager", 
"org.freedesktop.Hal")
    {
        std::vector< DBus::Path > udis;
        GetAllDevices(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;
        _devices.erase(udi);
    }

Anyway, anyone interested???

---

1: The introspection was generated in python via:
    >>> import dbus
    >>> bus=dbus.SystemBus()
    >>> obj=bus.get_object('org.freedesktop.Hal', 
'/org/freedesktop/Hal/Manager')
    >>> obj.Introspect()
    u'<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object 
Introspection 
1.0//EN"\n"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">\n<node>\n  

    <interface name="org.freedesktop.DBus.Introspectable">\n    <method 
name="Introspect">\n      <arg name="data" direction="out" 
type="s"/>\n    </method>\n 
    </interface>\n  <interface name="org.freedesktop.Hal.Manager">\n    
<method name="GetAllDevices">\n      <arg name="devices" direction="out" 
type="ao"/>\n   
    </method>\n    <method name="DeviceExists">\n      <arg 
name="does_it_exist" direction="out" type="b"/>\n      <arg name="udi" 
direction="in" type="o"/>\n   
    </method>\n    <method name="FindDeviceStringMatch">\n      <arg 
name="devices" direction="out" type="ao"/>\n      <arg name="key" 
direction="in" type="s"/>\n     
    <arg name="value" direction="in" type="s"/>\n    </method>\n    
<method name="FindDeviceByCapability">\n      <arg name="devices" 
direction="out" type="ao"/>\n     
    <arg name="capability" direction="in" type="s"/>\n    </method>\n    
<method name="NewDevice">\n      <arg name="temporary_udi" 
direction="out" type="s"/>\n   
    </method>\n    <method name="Remove">\n      <arg name="udi" 
direction="in" type="s"/>\n    </method>\n    <method 
name="CommitToGdl">\n     
    <arg name="temporary_udi" direction="in" type="s"/>\n      <arg     
name="global_udi" direction="in" type="s"/>\n    </method>\n  
</interface>\n</node>\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 
the introspection



More information about the dbus mailing list