D-BUS C++: method marshalling objects
David Eriksson
twogood at users.sourceforge.net
Tue Oct 11 02:13:20 PDT 2005
Murray Cumming, Paul Durante, and others who might be interested:
After studying Paul's "cbus" code I have made numerous improvements to
my own C++ wrapper for D-BUS. It is still very much a work in progress
but I have implemented an IMHO quite neat feature that you might know
how to make even better.
The template juggling is partly inspired by libsigc++ so Murray will
probably have ideas for improvement.
About my design:
I have one abstract base class for each interface I expose via D-BUS,
for example "Device". I have an implementation of this interface, for
example "DeviceImpl".
For each interface I expose via D-BUS I have a class (e.g.
"DeviceHandler") to handle method calls made to this interface for any
object.
In order to make this letter as short as possible I have left out a lot,
maybe too much. If you want to know more, just ask.
Improvements:
Previously I had a "HandleMessage" method in the handler class (for
example "DeviceHandler") that examined the member property of the
incoming message and called a method to marshall that method.
After looking at Paul's code I pulled myself together and replaced the
"HandleMessage" method with code to register the functions that
marshalled the individual D-BUS method calls.
However, I wasn't satisfied. The marshalling functions always looked the
same:
1. Decode parameters from incoming message
2. Call the corresponding method on the implementation object (eg. a
"DeviceImpl" object) with those parameters
3. Create reply message
4. Write return value (if any) to reply message
So I asked myself: how can I avoid writing that code again and again?
I had this function to register a method handler:
template<class U>
void RegisterMethod(
const std::string& name,
Message_ptr (U::*handler)(Object_ptr, Message_ptr))
But I wanted something like this:
void RegisterMethod(const std::string& name, method)
After some thinking and looking at libsigc++ I came up with multiple
functions like this, where T is the interface (e.g. "Device"):
template <class T_return>
void RegisterMethod(const std::string& name, T_return (T::*handler)())
template <class T_return, class T_arg1>
void RegisterMethod(const std::string& name, T_return (T::*handler)(T_arg1))
These functions create something I call (in lack of better knowledge of
the English language) "method marshalling objects", for example:
template <class T_object, class T_return,
class T_arg1>
class Method1 : public MethodBase<T_object>
{
public:
typedef boost::shared_ptr<T_object> Object_ptr;
typedef T_return (T_object::*HandlerType)(
T_arg1);
private:
HandlerType mHandler;
public:
Method1(
const std::string& name,
HandlerType handler) :
MethodBase<T_object>(name),
mHandler(handler)
{
}
virtual ~Method1()
{}
virtual Message_ptr HandleMessage(
Object_ptr object,
Message_ptr message)
{
T_arg1 arg1;
*message >> arg1;
Message_ptr reply(
Message::NewMethodReturn(message) );
*reply << (*object.*mHandler) (arg1);
return reply;
}
};
And voila! As long as I have a RegisterMethod function and a method
marshalling object for the right number of parameters, it's very simple
to add or remove methods on my D-BUS objects. Example from the
"DeviceHandler" constructor:
#define REGISTER_METHOD(method) RegisterMethod(#method, &Device::method)
REGISTER_METHOD(Disconnect);
REGISTER_METHOD(GetAddress);
REGISTER_METHOD(GetName);
REGISTER_METHOD(GetProperties);
REGISTER_METHOD(GetState);
#undef REGISTER_METHOD
One obstacle was void methods, so I have special RegisterMethod
functions and a method marshalling objects for those.
Another obstacle was that some of my interfaces passed parameters by
reference, for example const std::string&. This obviously does not work
with the implementation of my method marshalling objects seen above, so
I changed my interfaces to pass the strings by value instead.
The method marshalling objects would probably benefit from being
generated (like for example signal.h in libsigc++) but that's a future
improvement.
Is this any good or am I wasting my time?
--
Regards,
-\- David Eriksson -/-
SynCE - http://synce.sourceforge.net
ScummVM - http://scummvm.sourceforge.net
Desquirr - http://desquirr.sourceforge.net
More information about the dbus
mailing list