Commit graph

7 commits

Author SHA1 Message Date
Patrick Ohly
950fa6857e gdbus: allow using private connection
This change was necessary because it turned out that using
g_dbus_setup_bus() and later dbus_g_bus_get() leads to problems
(assertion about watch data on Moblin 2.1, CRITICAL warning
and possibly other issues on Debian Lenny).

It seems that sharing a DBusConnection between different layers on top
of libdbus is either not supported or incorrectly implemented, at
least in glib-dbus.

The problem was found in SyncEvolution when using a libecal/ebook
which call D-Bus under the hood (Moblin Bugzilla #8460). SyncEvolution
has no control over those calls, therefore making the connection used
by the syncevo-dbus-server private was the easier alternative.
2009-12-04 12:47:47 +01:00
Patrick Ohly
bb73c2745b gdbus C++: demonstrate how to bind methods in private base classes
Passing the "this" pointer to DBusObjectHelper::add() does not
work in this case because it cannot downcast to the required
base class. However, the caller can do that, which solves the
problem.
2009-10-14 12:28:02 +02:00
Patrick Ohly
fce06ca799 gdbus C++ example: added static and const function callback
The const method does not work at the moment and therefore
is commented out. The underlying problem is that the DBusObjectHelper::add()
call must be able to determine the method pointer type without the
const qualifier. All attempts to write a template function where
"M" is a normal function pointer and "method" a const member pointer
failed with compiler errors or didn't have the desired effect.
2009-10-14 12:28:01 +02:00
Patrick Ohly
7f81e1593a gdbus C++: simplified method declaration
It is no longer necessary to duplicate the list of function parameters
when declaring a D-Bus methods. Instead methods are added to a
DBusObjectHelper instance with the minimum amount of information:
- optional this pointer for methods
- the address of the method, global or static function
- the name of the D-Bus method

The DBusHelper::add() call determines the signature based on the
function pointer. It would have been nice to pass a boost::bind()
result and that way get rid of the special case of method pointers,
but it seems to be impossible to determine the type of all parameters
in the functor returned by boost::bind().

The maximum number of parameters of methods, including the "this"
pointer, is now 9, the maximum supported by boost::bind().

Internally DBusHelper maintains a DBusMethodTable with one pointer to
a boost::function instance for each method. This depends on the new
libgdbus per-method callback data.

Signals are also added with add() and likewise maintained inside the
DBusObjectHelper. This avoids duplicating the signal name.

All strings passed to DBusObjectHelper are copied and freed when no
longer needed.

The old handling of asynchronous method implementations via dedicated
method callbacks was replaced with code that detects when a method ask
for a Result* parameter. This is done via dbus_traits for those
parameter types, similar to the way how Watches were handled. The
compiler can detect this situation at compile time, which should
remove the useless post-method handling of the return values from the
generated code.

The main advantage is that the exponential duplication of code for the
various combinations of n arguments and m asynchronous result values
could be removed. It is nicer for users, too, because the _ASYNC flag
no longer has to be specified manually when registering the method.
2009-10-14 12:28:01 +02:00
Patrick Ohly
7b5ae309bf D-Bus C++: added support for structs
Members of structs must be read- and writeable
because the marshaling code accesses them directly.
The dbus_traits then can be defined by deriving
from dbus_struct_traits with template parameters
which describe the struct members.
2009-10-07 16:11:33 +02:00
Patrick Ohly
b435d87392 D-Bus C++: added the possibility to pass Caller ID string and a watch
Use
    const Caller_t &caller
to get a caller ID string. Caller_t is a class which mimicks a
string, which is necessary to distinguish this parameter
from a std::string parameter passed via D-Bus.

Use
    const boost::shared_ptr<Watch> &watch
to be called with an active watch on the caller.
The callback invoked by the Watch must be set
with setCallback().
2009-10-07 16:11:20 +02:00
Patrick Ohly
0fb5794a21 D-Bus C++: C++ helper classes for libdbus/libgdbus
C++ classes and templates provided by header files simplify
programming in C++ with libdbus and libgdbus. libdbus items are
tracked with Boost shared pointers. Errors are turned into
exceptions. The binding to C++ is done via templates which provide the
C-style callbacks and declarations expected by libgdbus and map to
standard C++ types and STL data structures. Neither code generator nor
library code is required.

Synchronous and asynchronous method implementation are supported.
Asynchronous result deliver is done via a callback object with a
C++ signature that matches the values which have to be returned.

Due to the lack of variadic templates, lots of similar templates have
to be written to cover methods with varying combinations of arguments
and return codes. Not particularly elegant, but the alternative would
be to introduce a code generator, which has its own
drawbacks. Currently up to 10 items per method are supported, where
the number of items include the optional return value, arguments and
retvals.

Setting a Watch (base class) notifies the implementor of an when his
caller disconnects.  This can be used to abort a long-running method
when the consumer of the result goes away.

Callers are identified by their unique Bus ID, represented as Caller_t,
an alias for a plain std::string.

Objects are represented by their path with a DBusObject_t, again a
plain std::string. By default, each path comes with one interface
(DBusObject). It is possible to instantiate multiple DBusObjects with
the same path, which appears on D-Bus as a single object with multiple
interfaces.

The DBusObjectHelper simplifies object handling. It stores the
necessary information and connection reference so that the object can
be unregistered when the DBusObjectHelper is destroyed. The intended
usage is that classes own instances of DBusObjectHelper and activate
those with a method table that points to class methods.

Signals are handled as instances of EmitSignalX templates where X
stands for the number of parameters, pretty much like ResultX
callbacks are handled. The function call operator emits the signal,
with the auxiliary information (D-Bus signal name) set when
instantiating the EmitSignalX object as part of a class. The D-Bus
connection and interface is provided at the time of the signal
emission by the parent DBusObject.

The table entry for the signal is created by a static member function
of the template, which allows building a static table as required by
gdbus. Note that the signal name must be passed into that
function. This slight duplication is necessary because the template
cannot be parameterized with a string constant. Turning
makeSignalEntry() into a normal member function would make it
difficult to build the signal table.

DBusErrorCXX is a helper class for DBusError which automatically
initializes the struct, can be used to check for an error and throws
an exception for it.
2009-10-07 16:11:20 +02:00