d743a029f4b77eaa3b746886eace1a841b1095bf
[platform/upstream/syncevolution.git] / src / gdbus / gdbus-cxx-bridge.h
1 /*
2  * Copyright (C) 2009 Intel Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) version 3.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301  USA
18  */
19
20 /**
21  * This file contains everything that a D-Bus server needs to
22  * integrate a normal C++ class into D-Bus. Argument and result
23  * marshaling is done in wrapper functions which convert directly
24  * to normal C++ types (bool, integers, std::string, std::map<>, ...).
25  * See dbus_traits for the full list of supported types.
26  *
27  * Before explaining the binding, some terminology first:
28  * - A function has a return type and multiple parameters.
29  * - Input parameters are read-only arguments of the function.
30  * - The function can return values to the caller via the
31  *   return type and output parameters (retvals).
32  *
33  * The C++ binding roughly looks like this:
34  * - Arguments can be passed as plain types or const references:
35      void foo(int arg); void bar(const std::string &str);
36  * - A single result can be returned as return value:
37  *   int foo();
38  * - Multiple results can be copied into instances provided by
39  *   the wrapper, passed by reference: void foo(std::string &res);
40  * - A return value, arguments and retvals can be combined
41  *   arbitrarily. In the D-Bus reply the return code comes before
42  *   all return values.
43  *
44  * Asynchronous methods are possible by declaring one parameter as a
45  * Result pointer and later calling the virtual function provided by
46  * it. Parameter passing of results is less flexible than that of
47  * method parameters: the later allows both std::string as well as
48  * const std::string &, for results only the const reference is
49  * supported. The Result instance is passed as pointer and then owned
50  * by the called method.
51  *
52  * Reference counting via boost::intrusive_ptr ensures that all
53  * D-Bus objects are handled automatically internally.
54  */
55
56
57 #ifndef INCL_GDBUS_CXX_BRIDGE
58 #define INCL_GDBUS_CXX_BRIDGE
59
60 #include "gdbus.h"
61 #include "gdbus-cxx.h"
62
63 #include <map>
64 #include <vector>
65
66 #include <boost/bind.hpp>
67 #include <boost/intrusive_ptr.hpp>
68 #include <boost/shared_ptr.hpp>
69
70 namespace boost {
71     void intrusive_ptr_add_ref(DBusConnection *con) { dbus_connection_ref(con); }
72     void intrusive_ptr_release(DBusConnection *con) { dbus_connection_unref(con); }
73     void intrusive_ptr_add_ref(DBusMessage *msg) { dbus_message_ref(msg); }
74     void intrusive_ptr_release(DBusMessage *msg) { dbus_message_unref(msg); }
75 }
76
77 class DBusConnectionPtr : public boost::intrusive_ptr<DBusConnection>
78 {
79  public:
80     DBusConnectionPtr() {}
81     // connections are typically created once, so increment the ref counter by default
82     DBusConnectionPtr(DBusConnection *conn, bool add_ref = true) :
83       boost::intrusive_ptr<DBusConnection>(conn, add_ref)
84     {}
85
86     DBusConnection *reference(void) throw()
87     {
88         DBusConnection *conn = get();
89         dbus_connection_ref(conn);
90         return conn;
91     }
92 };
93
94 class DBusMessagePtr : public boost::intrusive_ptr<DBusMessage>
95 {
96  public:
97     DBusMessagePtr() {}
98     // expected to be used for messages created anew,
99     // so use the reference already incremented for us
100     // and don't increment by default
101     DBusMessagePtr(DBusMessage *msg, bool add_ref = false) :
102       boost::intrusive_ptr<DBusMessage>(msg, add_ref)
103     {}
104
105     DBusMessage *reference(void) throw()
106     {
107         DBusMessage *msg = get();
108         dbus_message_ref(msg);
109         return msg;
110     }
111 };
112
113 /**
114  * wrapper around DBusError which initializes
115  * the struct automatically, then can be used to
116  * throw an exception
117  */
118 class DBusErrorCXX : public DBusError
119 {
120  public:
121     DBusErrorCXX() { dbus_error_init(this); }
122     void throwFailure(const std::string &operation)
123     {
124         if (dbus_error_is_set(this)) {
125             throw std::runtime_error(operation + ": " + message);
126         } else {
127             throw std::runtime_error(operation + " failed");
128         }
129     }
130
131     operator bool ()
132     {
133         return dbus_error_is_set(this);
134     }
135 };
136
137 /**
138  * Special type for object paths. A string in practice.
139  */
140 class DBusObject_t : public std::string
141 {
142  public:
143     DBusObject_t() {}
144     template <class T> DBusObject_t(T val) : std::string(val) {}
145     template <class T> DBusObject_t &operator = (T val) { assign(val); return *this; }
146 };
147
148 /**
149  * specializations of this must defined methods for encoding and
150  * decoding type C and declare its signature
151  */
152 template<class C> struct dbus_traits {};
153
154 struct dbus_traits_base
155 {
156     /**
157      * A C++ method or function can handle a call asynchronously by
158      * asking to be passed a "boost::shared_ptr<Result*>" parameter.
159      * The dbus_traits for those parameters have "asynchronous" set to
160      * true, which skips all processing after calling the method.
161      */
162     static const bool asynchronous = false;
163 };
164
165 /**
166  * Append a varying number of parameters as result to the
167  * message. Types can be anything that has a dbus_traits, including
168  * types which are normally recognized as input parameters in D-Bus
169  * method calls.
170  */
171 template <class A1, class A2, class A3, class A4, class A5,
172     class A6, class A7, class A8, class A9, class A10>
173 void append_retvals(DBusMessagePtr &msg,
174                     A1 a1,
175                     A2 a2,
176                     A3 a3,
177                     A4 a4,
178                     A5 a5,
179                     A6 a6,
180                     A7 a7,
181                     A8 a8,
182                     A9 a9,
183                     A10 a10)
184 {
185     DBusMessageIter iter;
186     dbus_message_iter_init_append(msg.get(), &iter);
187     dbus_traits<A1>::append_retval(iter, a1);
188     dbus_traits<A2>::append_retval(iter, a2);
189     dbus_traits<A3>::append_retval(iter, a3);
190     dbus_traits<A4>::append_retval(iter, a4);
191     dbus_traits<A5>::append_retval(iter, a5);
192     dbus_traits<A6>::append_retval(iter, a6);
193     dbus_traits<A7>::append_retval(iter, a7);
194     dbus_traits<A8>::append_retval(iter, a8);
195     dbus_traits<A9>::append_retval(iter, a9);
196     dbus_traits<A10>::append_retval(iter, a10);
197 }
198
199 template <class A1, class A2, class A3, class A4, class A5,
200     class A6, class A7, class A8, class A9>
201 void append_retvals(DBusMessagePtr &msg,
202                     A1 a1,
203                     A2 a2,
204                     A3 a3,
205                     A4 a4,
206                     A5 a5,
207                     A6 a6,
208                     A7 a7,
209                     A8 a8,
210                     A9 a9)
211 {
212     DBusMessageIter iter;
213     dbus_message_iter_init_append(msg.get(), &iter);
214     dbus_traits<A1>::append_retval(iter, a1);
215     dbus_traits<A2>::append_retval(iter, a2);
216     dbus_traits<A3>::append_retval(iter, a3);
217     dbus_traits<A4>::append_retval(iter, a4);
218     dbus_traits<A5>::append_retval(iter, a5);
219     dbus_traits<A6>::append_retval(iter, a6);
220     dbus_traits<A7>::append_retval(iter, a7);
221     dbus_traits<A8>::append_retval(iter, a8);
222     dbus_traits<A9>::append_retval(iter, a9);
223 }
224
225 template <class A1, class A2, class A3, class A4, class A5,
226     class A6, class A7, class A8>
227 void append_retvals(DBusMessagePtr &msg,
228                     A1 a1,
229                     A2 a2,
230                     A3 a3,
231                     A4 a4,
232                     A5 a5,
233                     A6 a6,
234                     A7 a7,
235                     A8 a8)
236 {
237     DBusMessageIter iter;
238     dbus_message_iter_init_append(msg.get(), &iter);
239     dbus_traits<A1>::append_retval(iter, a1);
240     dbus_traits<A2>::append_retval(iter, a2);
241     dbus_traits<A3>::append_retval(iter, a3);
242     dbus_traits<A4>::append_retval(iter, a4);
243     dbus_traits<A5>::append_retval(iter, a5);
244     dbus_traits<A6>::append_retval(iter, a6);
245     dbus_traits<A7>::append_retval(iter, a7);
246     dbus_traits<A8>::append_retval(iter, a8);
247 }
248
249 template <class A1, class A2, class A3, class A4, class A5,
250     class A6, class A7>
251 void append_retvals(DBusMessagePtr &msg,
252                     A1 a1,
253                     A2 a2,
254                     A3 a3,
255                     A4 a4,
256                     A5 a5,
257                     A6 a6,
258                     A7 a7)
259 {
260     DBusMessageIter iter;
261     dbus_message_iter_init_append(msg.get(), &iter);
262     dbus_traits<A1>::append_retval(iter, a1);
263     dbus_traits<A2>::append_retval(iter, a2);
264     dbus_traits<A3>::append_retval(iter, a3);
265     dbus_traits<A4>::append_retval(iter, a4);
266     dbus_traits<A5>::append_retval(iter, a5);
267     dbus_traits<A6>::append_retval(iter, a6);
268     dbus_traits<A7>::append_retval(iter, a7);
269 }
270
271 template <class A1, class A2, class A3, class A4, class A5,
272     class A6>
273 void append_retvals(DBusMessagePtr &msg,
274                     A1 a1,
275                     A2 a2,
276                     A3 a3,
277                     A4 a4,
278                     A5 a5,
279                     A6 a6)
280 {
281     DBusMessageIter iter;
282     dbus_message_iter_init_append(msg.get(), &iter);
283     dbus_traits<A1>::append_retval(iter, a1);
284     dbus_traits<A2>::append_retval(iter, a2);
285     dbus_traits<A3>::append_retval(iter, a3);
286     dbus_traits<A4>::append_retval(iter, a4);
287     dbus_traits<A5>::append_retval(iter, a5);
288     dbus_traits<A6>::append_retval(iter, a6);
289 }
290
291 template <class A1, class A2, class A3, class A4, class A5>
292 void append_retvals(DBusMessagePtr &msg,
293                     A1 a1,
294                     A2 a2,
295                     A3 a3,
296                     A4 a4,
297                     A5 a5)
298 {
299     DBusMessageIter iter;
300     dbus_message_iter_init_append(msg.get(), &iter);
301     dbus_traits<A1>::append_retval(iter, a1);
302     dbus_traits<A2>::append_retval(iter, a2);
303     dbus_traits<A3>::append_retval(iter, a3);
304     dbus_traits<A4>::append_retval(iter, a4);
305     dbus_traits<A5>::append_retval(iter, a5);
306 }
307
308 template <class A1, class A2, class A3, class A4>
309 void append_retvals(DBusMessagePtr &msg,
310                     A1 a1,
311                     A2 a2,
312                     A3 a3,
313                     A4 a4)
314 {
315     DBusMessageIter iter;
316     dbus_message_iter_init_append(msg.get(), &iter);
317     dbus_traits<A1>::append_retval(iter, a1);
318     dbus_traits<A2>::append_retval(iter, a2);
319     dbus_traits<A3>::append_retval(iter, a3);
320     dbus_traits<A4>::append_retval(iter, a4);
321 }
322
323 template <class A1, class A2, class A3>
324 void append_retvals(DBusMessagePtr &msg,
325                     A1 a1,
326                     A2 a2,
327                     A3 a3)
328 {
329     DBusMessageIter iter;
330     dbus_message_iter_init_append(msg.get(), &iter);
331     dbus_traits<A1>::append_retval(iter, a1);
332     dbus_traits<A2>::append_retval(iter, a2);
333     dbus_traits<A3>::append_retval(iter, a3);
334 }
335
336 template <class A1, class A2>
337 void append_retvals(DBusMessagePtr &msg,
338                     A1 a1,
339                     A2 a2)
340 {
341     DBusMessageIter iter;
342     dbus_message_iter_init_append(msg.get(), &iter);
343     dbus_traits<A1>::append_retval(iter, a1);
344     dbus_traits<A2>::append_retval(iter, a2);
345 }
346
347 template <class A1>
348 void append_retvals(DBusMessagePtr &msg,
349                     A1 a1)
350 {
351     DBusMessageIter iter;
352     dbus_message_iter_init_append(msg.get(), &iter);
353     dbus_traits<A1>::append_retval(iter, a1);
354 }
355
356 /**
357  * interface expected by EmitSignal
358  */
359 class DBusObject
360 {
361  public:
362     virtual ~DBusObject() {}
363
364     virtual DBusConnection *getConnection() const = 0;
365     virtual const char *getPath() const = 0;
366     virtual const char *getInterface() const = 0;
367 };
368
369 class EmitSignal0
370 {
371     const DBusObject &m_object;
372     const std::string m_signal;
373
374  public:
375     EmitSignal0(const DBusObject &object,
376                 const std::string &signal) :
377         m_object(object),
378         m_signal(signal)
379     {}
380
381     void operator () ()
382     {
383         DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
384                                                    m_object.getInterface(),
385                                                    m_signal.c_str()));
386         if (!msg) {
387             throw std::runtime_error("dbus_message_new_signal() failed");
388         }
389
390         if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
391             throw std::runtime_error("dbus_connection_send failed");
392         }
393     }
394
395     GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
396     {
397         GDBusSignalTable entry;
398         entry.name = m_signal.c_str();
399         std::string buffer;
400         entry.signature = strdup(buffer.c_str());
401         entry.flags = flags;
402         return entry;
403     }
404 };
405
406 template <typename A1>
407 class EmitSignal1
408 {
409     const DBusObject &m_object;
410     const std::string m_signal;
411
412  public:
413     EmitSignal1(const DBusObject &object,
414                 const std::string &signal) :
415         m_object(object),
416         m_signal(signal)
417     {}
418
419     void operator () (A1 a1)
420     {
421         DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
422                                                    m_object.getInterface(),
423                                                    m_signal.c_str()));
424         if (!msg) {
425             throw std::runtime_error("dbus_message_new_signal() failed");
426         }
427         append_retvals(msg, a1);
428
429         if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
430             throw std::runtime_error("dbus_connection_send failed");
431         }
432     }
433
434     GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
435     {
436         GDBusSignalTable entry;
437         entry.name = m_signal.c_str();
438         std::string buffer;
439         buffer += dbus_traits<A1>::getSignature();
440         entry.signature = strdup(buffer.c_str());
441         entry.flags = flags;
442         return entry;
443     }
444 };
445
446 template <typename A1, typename A2>
447 class EmitSignal2
448 {
449     const DBusObject &m_object;
450     const std::string m_signal;
451
452  public:
453     EmitSignal2(const DBusObject &object,
454                 const std::string &signal) :
455         m_object(object),
456         m_signal(signal)
457     {}
458
459     void operator () (A1 a1, A2 a2)
460     {
461         DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
462                                                    m_object.getInterface(),
463                                                    m_signal.c_str()));
464         if (!msg) {
465             throw std::runtime_error("dbus_message_new_signal() failed");
466         }
467         append_retvals(msg, a1, a2);
468
469         if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
470             throw std::runtime_error("dbus_connection_send failed");
471         }
472     }
473
474     GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
475     {
476         GDBusSignalTable entry;
477         entry.name = m_signal.c_str();
478         std::string buffer;
479         buffer += dbus_traits<A1>::getSignature();
480         buffer += dbus_traits<A2>::getSignature();
481         entry.signature = strdup(buffer.c_str());
482         entry.flags = flags;
483         return entry;
484     }
485 };
486
487 template <typename A1, typename A2, typename A3>
488 class EmitSignal3
489 {
490     const DBusObject &m_object;
491     const std::string m_signal;
492
493  public:
494     EmitSignal3(const DBusObject &object,
495                 const std::string &signal) :
496         m_object(object),
497         m_signal(signal)
498     {}
499
500     void operator () (A1 a1, A2 a2, A3 a3)
501     {
502         DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
503                                                    m_object.getInterface(),
504                                                    m_signal.c_str()));
505         if (!msg) {
506             throw std::runtime_error("dbus_message_new_signal() failed");
507         }
508         append_retvals(msg, a1, a2, a3);
509         if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
510             throw std::runtime_error("dbus_connection_send failed");
511         }
512     }
513
514     GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
515     {
516         GDBusSignalTable entry;
517         entry.name = m_signal.c_str();
518         std::string buffer;
519         buffer += dbus_traits<A1>::getSignature();
520         buffer += dbus_traits<A2>::getSignature();
521         buffer += dbus_traits<A3>::getSignature();
522         entry.signature = strdup(buffer.c_str());
523         entry.flags = flags;
524         return entry;
525     }
526 };
527
528 template <typename A1, typename A2, typename A3, typename A4>
529 class EmitSignal4
530 {
531     const DBusObject &m_object;
532     const std::string m_signal;
533
534  public:
535     EmitSignal4(const DBusObject &object,
536                 const std::string &signal) :
537         m_object(object),
538         m_signal(signal)
539     {}
540
541     void operator () (A1 a1, A2 a2, A3 a3, A4 a4)
542     {
543         DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
544                                                    m_object.getInterface(),
545                                                    m_signal.c_str()));
546         if (!msg) {
547             throw std::runtime_error("dbus_message_new_signal() failed");
548         }
549         append_retvals(msg, a1, a2, a3, a4);
550         if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
551             throw std::runtime_error("dbus_connection_send failed");
552         }
553     }
554
555     GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
556     {
557         GDBusSignalTable entry;
558         entry.name = m_signal.c_str();
559         std::string buffer;
560         buffer += dbus_traits<A1>::getSignature();
561         buffer += dbus_traits<A2>::getSignature();
562         buffer += dbus_traits<A3>::getSignature();
563         buffer += dbus_traits<A4>::getSignature();
564         entry.signature = strdup(buffer.c_str());
565         entry.flags = flags;
566         return entry;
567     }
568 };
569
570 template <typename A1, typename A2, typename A3, typename A4, typename A5>
571 class EmitSignal5
572 {
573     const DBusObject &m_object;
574     const std::string m_signal;
575
576  public:
577     EmitSignal5(const DBusObject &object,
578                 const std::string &signal) :
579         m_object(object),
580         m_signal(signal)
581     {}
582
583     void operator () (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
584     {
585         DBusMessagePtr msg(dbus_message_new_signal(m_object.getPath(),
586                                                    m_object.getInterface(),
587                                                    m_signal.c_str()));
588         if (!msg) {
589             throw std::runtime_error("dbus_message_new_signal() failed");
590         }
591         append_retvals(msg, a1, a2, a3, a4, a5);
592         if (!dbus_connection_send(m_object.getConnection(), msg.get(), NULL)) {
593             throw std::runtime_error("dbus_connection_send failed");
594         }
595     }
596
597     GDBusSignalTable makeSignalEntry(GDBusSignalFlags flags = G_DBUS_SIGNAL_FLAG_NONE) const
598     {
599         GDBusSignalTable entry;
600         entry.name = m_signal.c_str();
601         std::string buffer;
602         buffer += dbus_traits<A1>::getSignature();
603         buffer += dbus_traits<A2>::getSignature();
604         buffer += dbus_traits<A3>::getSignature();
605         buffer += dbus_traits<A4>::getSignature();
606         buffer += dbus_traits<A5>::getSignature();
607         entry.signature = strdup(buffer.c_str());
608         entry.flags = flags;
609         return entry;
610     }
611 };
612
613 template <class M>
614 struct MakeMethodEntry
615 {
616     // There is no generic implementation of this method.
617     // If you get an error about it missing, then write
618     // a specialization for your type M (the method pointer).
619     //
620     // static GDBusMethodTable make(const char *name,
621     //                              GDBusMethodFlags flags)
622 };
623
624 /**
625  * Storage for method/signal/property arrays.
626  * Always contains at least one empty element
627  * at the end or is NULL.
628  */
629 template <class T> class DBusVector {
630     size_t m_entries;
631     size_t m_size;
632     T *m_elements;
633
634     static void destroy(GDBusMethodTable &entry) {
635         free(const_cast<char *>(entry.name));
636         free(const_cast<char *>(entry.signature));
637         free(const_cast<char *>(entry.reply));
638         if (entry.destroy) {
639             entry.destroy(&entry);
640         }
641     }
642
643     static void destroy(GDBusSignalTable &entry) {
644         free(const_cast<char *>(entry.signature));
645         // if (entry.destroy) {
646         // entry.destroy(&entry);
647         // }
648     }
649
650  public:
651     DBusVector() : m_entries(0), m_size(0), m_elements(NULL) {}
652     ~DBusVector() {
653         if (m_elements) {
654             for (size_t i = 0; i < m_entries; i++) {
655                 destroy(m_elements[i]);
656             }
657             free(m_elements);
658         }
659     }
660
661     T *get() { return m_elements; }
662     void push_back(const T &element) {
663         if (m_entries + 1 >= m_size) {
664             size_t newSize = m_size ? m_size * 2 : 16;
665             m_elements = static_cast<T *>(realloc(m_elements, newSize * sizeof(T)));
666             if (!m_elements) {
667                 throw std::bad_alloc();
668             }
669             m_size = newSize;
670         }
671         m_elements[m_entries] = element;
672         m_entries++;
673         memset(m_elements + m_entries, 0, sizeof(T));
674     }
675 };
676
677 /**
678  * utility class for registering an interface
679  */
680 class DBusObjectHelper : public DBusObject
681 {
682     DBusConnectionPtr m_conn;
683     std::string m_path;
684     std::string m_interface;
685     bool m_activated;
686     DBusVector<GDBusMethodTable> m_methods;
687     DBusVector<GDBusSignalTable> m_signals;
688
689  public:
690     DBusObjectHelper(DBusConnection *conn,
691                      const std::string &path,
692                      const std::string &interface) :
693         m_conn(conn),
694         m_path(path),
695         m_interface(interface),
696         m_activated(false)
697     {
698     }
699
700     ~DBusObjectHelper()
701     {
702         deactivate();
703     }
704
705     virtual DBusConnection *getConnection() const { return m_conn.get(); }
706     virtual const char *getPath() const { return m_path.c_str(); }
707     virtual const char *getInterface() const { return m_interface.c_str(); }
708
709     /**
710      * binds a member to the this pointer of its instance
711      * and invokes it when the specified method is called
712      */
713     template <class A1, class C, class M> void add(A1 instance, M C::*method,
714                                                    const char *name, GDBusMethodFlags flags = G_DBUS_METHOD_FLAG_NONE) {
715         typedef MakeMethodEntry< boost::function<M> > entry_type;
716         m_methods.push_back(entry_type::make(name, flags, entry_type::boostptr(method, instance)));
717     }
718
719
720     /**
721      * binds a plain function pointer with no additional arguments and
722      * invokes it when the specified method is called
723      */
724     template <class M> void add(M *function,
725                                 const char *name, GDBusMethodFlags flags = G_DBUS_METHOD_FLAG_NONE) {
726         m_methods.push_back(MakeMethodEntry< boost::function<M> >::make(name, flags, function));
727     }
728
729     /**
730      * add an existing signal entry
731      */
732     template <class S> void add(const S &s) {
733         m_signals.push_back(s.makeSignalEntry());
734     }
735
736     void activate(GDBusMethodTable *methods,
737                   GDBusSignalTable *signals,
738                   GDBusPropertyTable *properties,
739                   void *user_data) {
740         if (!g_dbus_register_interface(getConnection(), getPath(), getInterface(),
741                                        methods, signals, properties, user_data, NULL)) {
742             throw std::runtime_error(std::string("g_dbus_register_interface() failed for ") + getPath() + " " + getInterface());
743         }
744         m_activated = true;
745     }
746
747     void activate() {
748         if (!g_dbus_register_interface(getConnection(), getPath(), getInterface(),
749                                        m_methods.get(), m_signals.get(), NULL, NULL, NULL)) {
750             throw std::runtime_error(std::string("g_dbus_register_interface() failed for ") + getPath() + " " + getInterface());
751         }
752         m_activated = true;
753     }
754
755     void deactivate()
756     {
757         if (m_activated) {
758             if (!g_dbus_unregister_interface(getConnection(),
759                                              getPath(),
760                                              getInterface())) {
761                 throw std::runtime_error(std::string("g_dbus_unregister_interface() failed for ") + getPath() + " " + getInterface());
762             }
763             m_activated = false;
764         }
765     }
766 };
767
768
769 /**
770  * to be used for plain parameters like int32_t:
771  * treat as arguments which have to be extracted
772  * from the D-Bus message and can be skipped when
773  * encoding the reply
774  */
775 template<class host, int dbus> struct basic_marshal : public dbus_traits_base
776 {
777     typedef host host_type;
778     typedef host arg_type;
779     static const int dbus_type = dbus;
780
781     /**
782      * copy value from D-Bus iterator into variable
783      */
784     static void get(DBusConnection *conn, DBusMessage *msg,
785                     DBusMessageIter &iter, host &value)
786     {
787         if (dbus_message_iter_get_arg_type(&iter) != dbus) {
788             throw std::runtime_error("invalid argument");
789         }
790         dbus_message_iter_get_basic(&iter, &value);
791         dbus_message_iter_next(&iter);
792     }
793
794     /**
795      * copy value from return value into D-Bus iterator,
796      * empty here because plain types are no return values
797      */
798     static void append(DBusMessageIter &iter, arg_type value)
799     {
800         // nothing to do
801     }
802
803     /**
804      * utility function to be used by derived classes which
805      * need to copy a variable of this underlying type
806      */
807     static void append_retval(DBusMessageIter &iter, arg_type value)
808     {
809         if (!dbus_message_iter_append_basic(&iter, dbus, &value)) {
810             throw std::runtime_error("out of memory");
811         }
812     }
813 };
814
815 template<> struct dbus_traits<uint8_t> :
816     public basic_marshal< uint8_t, DBUS_TYPE_BYTE >
817 {
818     /**
819      * plain type, regardless of whether used as
820      * input or output parameter
821      */
822     static std::string getType() { return "y"; }
823
824     /**
825      * plain type => input parameter => non-empty signature
826      */
827     static std::string getSignature() {return getType(); }
828
829     /**
830      * plain type => not returned to caller
831      */
832     static std::string getReply() { return ""; }
833     
834 };
835
836 /** if the app wants to use signed char, let it and treat it like a byte */
837 template<> struct dbus_traits<int8_t> : dbus_traits<uint8_t>
838 {
839     typedef int8_t host_type;
840     typedef int8_t arg_type;
841
842     static void get(DBusConnection *conn, DBusMessage *msg,
843                     DBusMessageIter &iter, host_type &value)
844     {
845         dbus_traits<uint8_t>::get(conn, msg, iter, reinterpret_cast<uint8_t &>(value));
846     }
847 };
848
849 template<> struct dbus_traits<int16_t> :
850     public basic_marshal< int16_t, DBUS_TYPE_INT16 >
851 {
852     static std::string getType() { return "n"; }
853     static std::string getSignature() {return getType(); }
854     static std::string getReply() { return ""; }
855 };
856 template<> struct dbus_traits<uint16_t> :
857     public basic_marshal< uint16_t, DBUS_TYPE_UINT16 >
858 {
859     static std::string getType() { return "q"; }
860     static std::string getSignature() {return getType(); }
861     static std::string getReply() { return ""; }
862 };
863 template<> struct dbus_traits<int32_t> :
864     public basic_marshal< int32_t, DBUS_TYPE_INT32 >
865 {
866     static std::string getType() { return "i"; }
867     static std::string getSignature() {return getType(); }
868     static std::string getReply() { return ""; }
869 };
870 template<> struct dbus_traits<uint32_t> :
871     public basic_marshal< uint32_t, DBUS_TYPE_UINT32 >
872 {
873     static std::string getType() { return "u"; }
874     static std::string getSignature() {return getType(); }
875     static std::string getReply() { return ""; }
876 };
877
878 template<> struct dbus_traits<bool> : public dbus_traits_base
879 {
880     static std::string getType() { return "b"; }
881     static std::string getSignature() {return getType(); }
882     static std::string getReply() { return ""; }
883     static const int dbus = DBUS_TYPE_BOOLEAN;
884
885     static void get(DBusConnection *conn, DBusMessage *msg,
886                     DBusMessageIter &iter, bool &value)
887     {
888         if (dbus_message_iter_get_arg_type(&iter) != dbus) {
889             throw std::runtime_error("invalid argument");
890         }
891         dbus_bool_t dbus_value;
892         dbus_message_iter_get_basic(&iter, &dbus_value);
893         dbus_message_iter_next(&iter);
894         value = dbus_value;
895     }    
896
897     static void append(DBusMessageIter &iter, bool value) {}
898
899     static void append_retval(DBusMessageIter &iter, bool value)
900     {
901         dbus_bool_t dbus_value = value;
902         if (!dbus_message_iter_append_basic(&iter, dbus, &dbus_value)) {
903             throw std::runtime_error("out of memory");
904         }
905     }
906
907     typedef bool host_type;
908     typedef bool arg_type;
909 };
910
911 template<> struct dbus_traits<std::string> : public dbus_traits_base
912 {
913     static std::string getType() { return "s"; }
914     static std::string getSignature() {return getType(); }
915     static std::string getReply() { return ""; }
916     static const int dbus = DBUS_TYPE_STRING;
917
918     static void get(DBusConnection *conn, DBusMessage *msg,
919                     DBusMessageIter &iter, std::string &value)
920     {
921         if (dbus_message_iter_get_arg_type(&iter) != dbus) {
922             throw std::runtime_error("invalid argument");
923         }
924         const char *str;
925         dbus_message_iter_get_basic(&iter, &str);
926         dbus_message_iter_next(&iter);
927         value = str;
928     }
929
930     static void append(DBusMessageIter &iter, const std::string &value) {}
931
932     static void append_retval(DBusMessageIter &iter, const std::string &value)
933     {
934         const char *str = value.c_str();
935         if (!dbus_message_iter_append_basic(&iter, dbus, &str)) {
936             throw std::runtime_error("out of memory");
937         }
938     }
939
940     typedef std::string host_type;
941     typedef const std::string &arg_type;
942 };
943
944 template <> struct dbus_traits<DBusObject_t> : public dbus_traits_base
945 {
946     static std::string getType() { return "o"; }
947     static std::string getSignature() {return getType(); }
948     static std::string getReply() { return ""; }
949     static const int dbus = DBUS_TYPE_OBJECT_PATH;
950
951     static void get(DBusConnection *conn, DBusMessage *msg,
952                     DBusMessageIter &iter, DBusObject_t &value)
953     {
954         if (dbus_message_iter_get_arg_type(&iter) != dbus) {
955             throw std::runtime_error("invalid argument");
956         }
957         const char *str;
958         dbus_message_iter_get_basic(&iter, &str);
959         dbus_message_iter_next(&iter);
960         value = str;
961     }
962
963     static void append(DBusMessageIter &iter, const DBusObject_t &value) {}
964
965     static void append_retval(DBusMessageIter &iter, const DBusObject_t &value)
966     {
967         const char *str = value.c_str();
968         if (!dbus_message_iter_append_basic(&iter, dbus, &str)) {
969             throw std::runtime_error("out of memory");
970         }
971     }
972
973     typedef DBusObject_t host_type;
974     typedef const DBusObject_t &arg_type;
975 };
976
977 /**
978  * pseudo-parameter: not part of D-Bus signature,
979  * but rather extracted from message attributes
980  */
981 template <> struct dbus_traits<Caller_t> : public dbus_traits_base
982 {
983     static std::string getType() { return ""; }
984     static std::string getSignature() { return ""; }
985     static std::string getReply() { return ""; }
986
987     static void get(DBusConnection *conn, DBusMessage *msg,
988                     DBusMessageIter &iter, Caller_t &value)
989     {
990         const char *peer = dbus_message_get_sender(msg);
991         if (!peer) {
992             throw std::runtime_error("D-Bus method call without sender?!");
993         }
994         value = peer;
995     }
996
997     static void append(DBusMessageIter &iter, const DBusObject_t &value) {}
998
999     typedef Caller_t host_type;
1000     typedef const Caller_t &arg_type;
1001 };
1002
1003 /**
1004  * Pass array of basic type plus its number of entries.
1005  * Can only be used in cases where the caller owns the
1006  * memory and can discard it when the call returns, in
1007  * other words, for method calls, asynchronous replys and
1008  * signals, but not for return values.
1009  */
1010 template<class V> struct dbus_traits< std::pair<size_t, const V *> > : public dbus_traits_base
1011 {
1012     static std::string getContainedType()
1013     {
1014         return dbus_traits<V>::getType();
1015     }
1016     static std::string getType()
1017     {
1018         return std::string("a") +
1019             dbus_traits<V>::getType();
1020     }
1021     static std::string getSignature() {return getType(); }
1022     static std::string getReply() { return ""; }
1023     typedef std::pair<size_t, const V *> host_type;
1024     typedef const host_type &arg_type;
1025
1026     static void get(DBusConnection *conn, DBusMessage *msg,
1027                     DBusMessageIter &iter, host_type &array)
1028     {
1029         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
1030             throw std::runtime_error("invalid argument");
1031         }
1032         DBusMessageIter sub;
1033         dbus_message_iter_recurse(&iter, &sub);
1034         int type = dbus_message_iter_get_arg_type(&sub);
1035         if (type != dbus_traits<V>::dbus_type) {
1036             throw std::runtime_error("invalid argument");
1037         }
1038         int nelements;
1039         typename dbus_traits<V>::host_type *data;
1040         dbus_message_iter_get_fixed_array(&sub, &data, &nelements);
1041         array.first = nelements;
1042         array.second = data;
1043         dbus_message_iter_next(&iter);
1044     }
1045
1046     static void append(DBusMessageIter &iter, arg_type array) {}
1047
1048     static void append_retval(DBusMessageIter &iter, arg_type array)
1049     {
1050         DBusMessageIter sub;
1051         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, getContainedType().c_str(), &sub) ||
1052             !dbus_message_iter_append_fixed_array(&sub, dbus_traits<V>::dbus_type, &array.second, array.first) ||
1053             !dbus_message_iter_close_container(&iter, &sub)) {
1054             throw std::runtime_error("out of memory");
1055         }
1056     }
1057 };
1058
1059 /**
1060  * a std::map - treat it like a D-Bus dict
1061  */
1062 template<class K, class V> struct dbus_traits< std::map<K, V> > : public dbus_traits_base
1063 {
1064     static std::string getContainedType()
1065     {
1066         return std::string("{") +
1067             dbus_traits<K>::getType() +
1068             dbus_traits<V>::getType() +
1069             "}";
1070     }
1071     static std::string getType()
1072     {
1073         return std::string("a") +
1074             getContainedType();
1075     }
1076     static std::string getSignature() {return getType(); }
1077     static std::string getReply() { return ""; }
1078     typedef std::map<K, V> host_type;
1079     typedef const std::map<K, V> &arg_type;
1080
1081     static void get(DBusConnection *conn, DBusMessage *msg,
1082                     DBusMessageIter &iter, host_type &dict)
1083     {
1084         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
1085             throw std::runtime_error("invalid argument");
1086         }
1087         DBusMessageIter sub;
1088         dbus_message_iter_recurse(&iter, &sub);
1089         int type;
1090         while ((type = dbus_message_iter_get_arg_type(&sub)) != DBUS_TYPE_INVALID) {
1091             if (type != DBUS_TYPE_DICT_ENTRY) {
1092                 throw std::runtime_error("invalid argument");
1093             }
1094             DBusMessageIter entry;
1095             dbus_message_iter_recurse(&sub, &entry);
1096             K key;
1097             V value;
1098             dbus_traits<K>::get(conn, msg, entry, key);
1099             dbus_traits<V>::get(conn, msg, entry, value);
1100             dict.insert(std::make_pair(key, value));
1101             dbus_message_iter_next(&sub);
1102         }
1103         dbus_message_iter_next(&iter);
1104     }
1105
1106     static void append(DBusMessageIter &iter, arg_type dict) {}
1107
1108     static void append_retval(DBusMessageIter &iter, arg_type dict)
1109     {
1110         DBusMessageIter sub;
1111         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, getContainedType().c_str(), &sub)) {
1112             throw std::runtime_error("out of memory");
1113         }
1114
1115         for(typename host_type::const_iterator it = dict.begin();
1116             it != dict.end();
1117             ++it) {
1118             DBusMessageIter entry;
1119             if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &entry)) {
1120                 throw std::runtime_error("out of memory");
1121             }
1122             dbus_traits<K>::append_retval(entry, it->first);
1123             dbus_traits<V>::append_retval(entry, it->second);
1124             if (!dbus_message_iter_close_container(&sub, &entry)) {
1125                 throw std::runtime_error("out of memory");
1126             }
1127         }
1128         if (!dbus_message_iter_close_container(&iter, &sub)) {
1129             throw std::runtime_error("out of memory");
1130         }
1131     }
1132 };
1133
1134 /**
1135  * a std::vector - maps to D-Bus array, but with inefficient marshaling
1136  * because we cannot get a base pointer for the whole array
1137  */
1138 template<class V> struct dbus_traits< std::vector<V> > : public dbus_traits_base
1139 {
1140     static std::string getContainedType()
1141     {
1142         return dbus_traits<V>::getType();
1143     }
1144     static std::string getType()
1145     {
1146         return std::string("a") +
1147             getContainedType();
1148     }
1149     static std::string getSignature() {return getType(); }
1150     static std::string getReply() { return ""; }
1151     typedef std::vector<V> host_type;
1152     typedef const std::vector<V> &arg_type;
1153
1154     static void get(DBusConnection *conn, DBusMessage *msg,
1155                     DBusMessageIter &iter, host_type &array)
1156     {
1157         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
1158             throw std::runtime_error("invalid argument");
1159         }
1160         DBusMessageIter sub;
1161         dbus_message_iter_recurse(&iter, &sub);
1162         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1163             V value;
1164             dbus_traits<V>::get(conn, msg, sub, value);
1165             array.push_back(value);
1166         }
1167         dbus_message_iter_next(&iter);
1168     }
1169
1170     static void append(DBusMessageIter &iter, arg_type array) {}
1171
1172     static void append_retval(DBusMessageIter &iter, arg_type array)
1173     {
1174         DBusMessageIter sub;
1175         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, getContainedType().c_str(), &sub)) {
1176             throw std::runtime_error("out of memory");
1177         }
1178
1179         for(typename host_type::const_iterator it = array.begin();
1180             it != array.end();
1181             ++it) {
1182             dbus_traits<V>::append_retval(sub, *it);
1183         }
1184         if (!dbus_message_iter_close_container(&iter, &sub)) {
1185             throw std::runtime_error("out of memory");
1186         }
1187     }
1188 };
1189
1190 /**
1191  * a single member m of type V in a struct K
1192  */
1193 template<class K, class V, V K::*m> struct dbus_member_single
1194 {
1195     static std::string getType()
1196     {
1197         return dbus_traits<V>::getType();
1198     }
1199     typedef V host_type;
1200
1201     static void get(DBusConnection *conn, DBusMessage *msg,
1202                     DBusMessageIter &iter, K &val)
1203     {
1204         dbus_traits<V>::get(conn, msg, iter, val.*m);
1205     }
1206
1207     static void append_retval(DBusMessageIter &iter, const K &val)
1208     {
1209         dbus_traits<V>::append_retval(iter, val.*m);
1210     }
1211 };
1212
1213 /**
1214  * a member m of type V in a struct K, followed by another dbus_member
1215  * or dbus_member_single to end the chain
1216  */
1217 template<class K, class V, V K::*m, class M> struct dbus_member
1218 {
1219     static std::string getType()
1220     {
1221         return dbus_traits<V>::getType() + M::getType();
1222     }
1223     typedef V host_type;
1224
1225     static void get(DBusConnection *conn, DBusMessage *msg,
1226                     DBusMessageIter &iter, K &val)
1227     {
1228         dbus_traits<V>::get(conn, msg, iter, val.*m);
1229         M::get(conn, msg, iter, val);
1230     }
1231
1232     static void append_retval(DBusMessageIter &iter, const K &val)
1233     {
1234         dbus_traits<V>::append_retval(iter, val.*m);
1235         M::append_retval(iter, val);
1236     }
1237 };
1238
1239 /**
1240  * a helper class which implements dbus_traits for
1241  * a class, use with:
1242  * struct foo { int a; std::string b;  };
1243  * template<> struct dbus_traits< foo > : dbus_struct_traits< foo,
1244  *                                                            dbus_member<foo, int, &foo::a,
1245  *                                                            dbus_member_single<foo, std::string, &foo::b> > > {};
1246  */
1247 template<class K, class M> struct dbus_struct_traits : public dbus_traits_base
1248 {
1249     static std::string getContainedType()
1250     {
1251         return M::getType();
1252     }
1253     static std::string getType()
1254     {
1255         return std::string("(") +
1256             getContainedType() +
1257             ")";
1258     }
1259     static std::string getSignature() {return getType(); }
1260     static std::string getReply() { return ""; }
1261     typedef K host_type;
1262     typedef const K &arg_type;
1263
1264     static void get(DBusConnection *conn, DBusMessage *msg,
1265                     DBusMessageIter &iter, host_type &val)
1266     {
1267         
1268         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRUCT) {
1269             throw std::runtime_error("invalid argument");
1270         }
1271         DBusMessageIter sub;
1272         dbus_message_iter_recurse(&iter, &sub);
1273         M::get(conn, msg, sub, val);
1274         dbus_message_iter_next(&iter);
1275     }
1276
1277     static void append(DBusMessageIter &iter, arg_type val) {}
1278
1279     static void append_retval(DBusMessageIter &iter, arg_type val)
1280     {
1281         DBusMessageIter sub;
1282         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, NULL, &sub)) {
1283             throw std::runtime_error("out of memory");
1284         }
1285         M::append_retval(sub, val);
1286         if (!dbus_message_iter_close_container(&iter, &sub)) {
1287             throw std::runtime_error("out of memory");
1288         }
1289     }
1290 };
1291
1292 /**
1293  * special case const reference parameter:
1294  * treat like pass-by-value input argument
1295  *
1296  * Example: const std::string &arg
1297  */
1298 template<class C> struct dbus_traits<const C &> : public dbus_traits<C> {};
1299
1300 /**
1301  * special case writeable reference parameter:
1302  * must be a return value, so provide our own
1303  * get() and pack() where get() doesn't do
1304  * anything and pack() really encodes the value
1305  *
1306  * Example: std::string &retval
1307  */
1308 template<class C> struct dbus_traits<C &> : public dbus_traits<C>
1309 {
1310     /**
1311      * skip when extracting input arguments
1312      */
1313     static void get(DBusConnection *conn, DBusMessage *msg,
1314                     DBusMessageIter &iter, C &value) {}
1315     static std::string getSignature() { return ""; }
1316
1317     /**
1318      * use utility function provided by underlying trait
1319      */
1320     static void append(DBusMessageIter &iter, const C &value)
1321     {
1322         dbus_traits<C>::append_retval(iter, value);
1323     }
1324     static std::string getReply() { return dbus_traits<C>::getType(); }
1325 };
1326
1327 /**
1328  * dbus-cxx base exception thrown in dbus server 
1329  * org.syncevolution.gdbus-cxx.Exception 
1330  * This base class only contains interfaces, no data members
1331  */
1332 class DBusCXXException 
1333 {
1334  public:
1335     /**
1336      * get exception name, used to convert to dbus error name
1337      * subclasses should override it
1338      */
1339     virtual std::string getName() const { return "org.syncevolution.gdbus-cxx.Exception"; }
1340
1341     /**
1342      * get error message
1343      */
1344     virtual const char* getMessage() const { return "unknown"; }
1345 };
1346
1347 static DBusMessage *handleException(DBusMessage *msg)
1348 {
1349     try {
1350 #ifdef DBUS_CXX_EXCEPTION_HANDLER
1351         return DBUS_CXX_EXCEPTION_HANDLER(msg);
1352 #else
1353         throw;
1354 #endif
1355     } catch (const dbus_error &ex) {
1356         return g_dbus_create_error(msg, ex.dbusName().c_str(), "%s", ex.what());
1357     } catch (const DBusCXXException &ex) {
1358         return g_dbus_create_error(msg, ex.getName().c_str(), "%s", ex.getMessage());
1359     } catch (const std::runtime_error &ex) {
1360         return g_dbus_create_error(msg, "org.syncevolution.gdbus-cxx.Exception", "%s", ex.what());
1361     } catch (...) {
1362         return g_dbus_create_error(msg, "org.syncevolution.gdbus-cxx.Exception", "unknown");
1363     }
1364 }
1365
1366 /**
1367  * Check presence of a certain D-Bus client.
1368  */
1369 class DBusWatch : public Watch
1370 {
1371     DBusConnectionPtr m_conn;
1372     boost::function<void (void)> m_callback;
1373     bool m_called;
1374     guint m_watchID;
1375
1376     static void disconnect(DBusConnection *connection,
1377                            void *user_data)
1378     {
1379         DBusWatch *watch = static_cast<DBusWatch *>(user_data);
1380         if (!watch->m_called) {
1381             watch->m_called = true;
1382             if (watch->m_callback) {
1383                 watch->m_callback();
1384             }
1385         }
1386     }
1387
1388  public:
1389     DBusWatch(const DBusConnectionPtr &conn,
1390               const boost::function<void (void)> &callback = boost::function<void (void)>()) :
1391         m_conn(conn),
1392         m_callback(callback),
1393         m_called(false),
1394         m_watchID(0)
1395     {
1396     }
1397
1398     virtual void setCallback(const boost::function<void (void)> &callback)
1399     {
1400         m_callback = callback;
1401         if (m_called && m_callback) {
1402             m_callback();
1403         }
1404     }
1405
1406     void activate(const char *peer)
1407     {
1408         if (!peer) {
1409             throw std::runtime_error("DBusWatch::activate(): no peer");
1410         }
1411
1412         // Install watch first ...
1413         m_watchID = g_dbus_add_disconnect_watch(m_conn.get(),
1414                                                 peer,
1415                                                 disconnect,
1416                                                 this,
1417                                                 NULL);
1418         if (!m_watchID) {
1419             throw std::runtime_error("g_dbus_add_disconnect_watch() failed");
1420         }
1421
1422         // ... then check that the peer really exists,
1423         // otherwise we'll never notice the disconnect.
1424         // If it disconnects while we are doing this,
1425         // then disconnect() will be called twice,
1426         // but it handles that.
1427         DBusErrorCXX error;
1428         if (!dbus_bus_name_has_owner(m_conn.get(),
1429                                      peer,
1430                                      &error)) {
1431             if (error) {
1432                 error.throwFailure("dbus_bus_name_has_owner()");
1433             }
1434             disconnect(m_conn.get(), this);
1435         }
1436     }
1437
1438     ~DBusWatch()
1439     {
1440         if (m_watchID) {
1441             if (!g_dbus_remove_watch(m_conn.get(), m_watchID)) {
1442                 // this may happen because the watch is
1443                 // removed automatically when it was triggered
1444             }
1445             m_watchID = 0;
1446         }
1447     }
1448 };
1449
1450 /**
1451  * pseudo-parameter: not part of D-Bus signature,
1452  * but rather extracted from message attributes
1453  */
1454 template <> struct dbus_traits< boost::shared_ptr<Watch> >  : public dbus_traits_base
1455 {
1456     static std::string getType() { return ""; }
1457     static std::string getSignature() { return ""; }
1458     static std::string getReply() { return ""; }
1459
1460     static void get(DBusConnection *conn, DBusMessage *msg,
1461                     DBusMessageIter &iter, boost::shared_ptr<Watch> &value)
1462     {
1463         boost::shared_ptr<DBusWatch> watch(new DBusWatch(conn));
1464         watch->activate(dbus_message_get_sender(msg));
1465         value = watch;
1466     }
1467
1468     static void append(DBusMessageIter &iter, const boost::shared_ptr<Watch> &value) {}
1469
1470     typedef boost::shared_ptr<Watch> host_type;
1471     typedef const boost::shared_ptr<Watch> &arg_type;
1472 };
1473
1474 /**
1475  * base class for D-Bus results,
1476  * keeps references to required objects and provides the
1477  * failed() method
1478  */
1479 class DBusResult : virtual public Result
1480 {
1481  protected:
1482     DBusConnectionPtr m_conn;     /**< connection via which the message was received */
1483     DBusMessagePtr m_msg;         /**< the method invocation message */
1484
1485  public:
1486     DBusResult(DBusConnection *conn,
1487                DBusMessage *msg) :
1488         m_conn(conn, true),
1489         m_msg(msg, true)
1490     {}
1491
1492     virtual void failed(const dbus_error &error)
1493     {
1494         if (!g_dbus_send_error(m_conn.get(), m_msg.get(),
1495                                error.dbusName().c_str(),
1496                                "%s", error.what())) {
1497             throw std::runtime_error("g_dbus_send_error() failed");
1498         }
1499     }
1500
1501     virtual Watch *createWatch(const boost::function<void (void)> &callback)
1502     {
1503         std::auto_ptr<DBusWatch> watch(new DBusWatch(m_conn, callback));
1504         watch->activate(dbus_message_get_sender(m_msg.get()));
1505         return watch.release();
1506     }
1507 };
1508
1509 class DBusResult0 :
1510     public Result0,
1511     public DBusResult
1512 {
1513  public:
1514     DBusResult0(DBusConnection *conn,
1515                 DBusMessage *msg) :
1516         DBusResult(conn, msg)
1517     {}
1518   
1519     virtual void done()
1520     {
1521         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1522         if (!reply) {
1523             throw std::runtime_error("no DBusMessage");
1524         }
1525         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1526             throw std::runtime_error("dbus_connection_send failed");
1527         }
1528     }
1529
1530     static std::string getSignature() { return ""; }
1531     static void append(DBusMessageIter &iter) {}
1532 };
1533
1534 template <typename A1>
1535 class DBusResult1 :
1536     public Result1<A1>,
1537     public DBusResult
1538 {
1539  public:
1540     DBusResult1(DBusConnection *conn,
1541                 DBusMessage *msg) :
1542         DBusResult(conn, msg)
1543     {}
1544   
1545     virtual void done(A1 a1)
1546     {
1547         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1548         if (!reply) {
1549             throw std::runtime_error("no DBusMessage");
1550         }
1551         append_retvals(reply, a1);
1552         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1553             throw std::runtime_error("dbus_connection_send failed");
1554         }
1555     }
1556
1557     static std::string getSignature() { return dbus_traits<A1>::getSignature(); }
1558
1559     static const bool asynchronous =
1560         dbus_traits<A1>::asynchronous;
1561 };
1562
1563 template <typename A1, typename A2>
1564 class DBusResult2 :
1565     public Result2<A1, A2>,
1566     public DBusResult
1567 {
1568  public:
1569     DBusResult2(DBusConnection *conn,
1570                 DBusMessage *msg) :
1571         DBusResult(conn, msg)
1572     {}
1573   
1574     virtual void done(A1 a1, A2 a2)
1575     {
1576         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1577         if (!reply) {
1578             throw std::runtime_error("no DBusMessage");
1579         }
1580         append_retvals(reply, a1, a2);
1581         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1582             throw std::runtime_error("dbus_connection_send failed");
1583         }
1584     }
1585
1586     static std::string getSignature() {
1587         return dbus_traits<A1>::getSignature() +
1588             DBusResult1<A2>::getSignature();
1589     }
1590
1591     static const bool asynchronous =
1592         dbus_traits<A1>::asynchronous ||
1593         DBusResult1<A2>::asynchronous;
1594 };
1595
1596 template <typename A1, typename A2, typename A3>
1597 class DBusResult3 :
1598     public Result3<A1, A2, A3>,
1599     public DBusResult
1600 {
1601  public:
1602     DBusResult3(DBusConnection *conn,
1603                 DBusMessage *msg) :
1604         DBusResult(conn, msg)
1605     {}
1606   
1607     virtual void done(A1 a1, A2 a2, A3 a3)
1608     {
1609         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1610         if (!reply) {
1611             throw std::runtime_error("no DBusMessage");
1612         }
1613         append_retvals(reply, a1, a2, a3);
1614         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1615             throw std::runtime_error("dbus_connection_send failed");
1616         }
1617     }
1618
1619     static std::string getSignature() {
1620         return dbus_traits<A1>::getSignature() +
1621             DBusResult2<A2, A3>::getSignature();
1622     }
1623
1624     static const bool asynchronous =
1625         dbus_traits<A1>::asynchronous ||
1626         DBusResult2<A2, A3>::asynchronous;
1627 };
1628
1629 template <typename A1, typename A2, typename A3, typename A4>
1630 class DBusResult4 :
1631     public Result4<A1, A2, A3, A4>,
1632     public DBusResult
1633 {
1634  public:
1635     DBusResult4(DBusConnection *conn,
1636                 DBusMessage *msg) :
1637         DBusResult(conn, msg)
1638     {}
1639   
1640     virtual void done(A1 a1, A2 a2, A3 a3, A4 a4)
1641     {
1642         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1643         if (!reply) {
1644             throw std::runtime_error("no DBusMessage");
1645         }
1646         append_retvals(reply, a1, a2, a3, a4);
1647         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1648             throw std::runtime_error("dbus_connection_send failed");
1649         }
1650     }
1651
1652     static std::string getSignature() {
1653         return dbus_traits<A1>::getSignature() +
1654             DBusResult3<A2, A3, A4>::getSignature();
1655     }
1656
1657     static const bool asynchronous =
1658         dbus_traits<A1>::asynchronous ||
1659         DBusResult3<A2, A3, A4>::asynchronous;
1660 };
1661
1662 template <typename A1, typename A2, typename A3, typename A4, typename A5>
1663 class DBusResult5 :
1664     public Result5<A1, A2, A3, A4, A5>,
1665     public DBusResult
1666 {
1667  public:
1668     DBusResult5(DBusConnection *conn,
1669                 DBusMessage *msg) :
1670         DBusResult(conn, msg)
1671     {}
1672   
1673     virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
1674     {
1675         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1676         if (!reply) {
1677             throw std::runtime_error("no DBusMessage");
1678         }
1679         append_retvals(reply, a1, a2, a3, a4, a5);
1680         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1681             throw std::runtime_error("dbus_connection_send failed");
1682         }
1683     }
1684
1685     static std::string getSignature() {
1686         return dbus_traits<A1>::getSignature() +
1687             DBusResult4<A2, A3, A4, A5>::getSignature();
1688     }
1689
1690     static const bool asynchronous =
1691         dbus_traits<A1>::asynchronous ||
1692         DBusResult4<A2, A3, A4, A5>::asynchronous;
1693 };
1694
1695 template <typename A1, typename A2, typename A3, typename A4, typename A5,
1696           typename A6>
1697 class DBusResult6 :
1698     public Result6<A1, A2, A3, A4, A5, A6>,
1699     public DBusResult
1700 {
1701  public:
1702     DBusResult6(DBusConnection *conn,
1703                 DBusMessage *msg) :
1704         DBusResult(conn, msg)
1705     {}
1706   
1707     virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
1708     {
1709         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1710         if (!reply) {
1711             throw std::runtime_error("no DBusMessage");
1712         }
1713         append_retvals(reply, a1, a2, a3, a4, a5, a6);
1714         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1715             throw std::runtime_error("dbus_connection_send failed");
1716         }
1717     }
1718
1719     static std::string getSignature() {
1720         return dbus_traits<A1>::getSignature() +
1721             DBusResult5<A2, A3, A4, A5, A6>::getSignature();
1722     }
1723
1724     static const bool asynchronous =
1725         dbus_traits<A1>::asynchronous ||
1726         DBusResult5<A2, A3, A4, A5, A6>::asynchronous;
1727 };
1728
1729 template <typename A1, typename A2, typename A3, typename A4, typename A5,
1730           typename A6, typename A7>
1731 class DBusResult7 :
1732     public Result7<A1, A2, A3, A4, A5, A6, A7>,
1733     public DBusResult
1734 {
1735  public:
1736     DBusResult7(DBusConnection *conn,
1737                 DBusMessage *msg) :
1738         DBusResult(conn, msg)
1739     {}
1740   
1741     virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
1742     {
1743         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1744         if (!reply) {
1745             throw std::runtime_error("no DBusMessage");
1746         }
1747         append_retvals(reply, a1, a2, a3, a4, a5, a6, a7);
1748         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1749             throw std::runtime_error("dbus_connection_send failed");
1750         }
1751     }
1752
1753     static std::string getSignature() {
1754         return dbus_traits<A1>::getSignature() +
1755             DBusResult6<A2, A3, A4, A5, A6, A7>::getSignature();
1756     }
1757
1758     static const bool asynchronous =
1759         dbus_traits<A1>::asynchronous ||
1760         DBusResult6<A2, A3, A4, A5, A6, A7>::asynchronous;
1761 };
1762
1763 template <typename A1, typename A2, typename A3, typename A4, typename A5,
1764           typename A6, typename A7, typename A8>
1765 class DBusResult8 :
1766     public Result8<A1, A2, A3, A4, A5, A6, A7, A8>,
1767     public DBusResult
1768 {
1769  public:
1770     DBusResult8(DBusConnection *conn,
1771                 DBusMessage *msg) :
1772         DBusResult(conn, msg)
1773     {}
1774   
1775     virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
1776     {
1777         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1778         if (!reply) {
1779             throw std::runtime_error("no DBusMessage");
1780         }
1781         append_retvals(reply, a1, a2, a3, a4, a5, a6, a7, a8);
1782         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1783             throw std::runtime_error("dbus_connection_send failed");
1784         }
1785     }
1786
1787     static std::string getSignature() {
1788         return dbus_traits<A1>::getSignature() +
1789             DBusResult7<A2, A3, A4, A5, A6, A7, A8>::getSignature();
1790     }
1791
1792     static const bool asynchronous =
1793         dbus_traits<A1>::asynchronous ||
1794         DBusResult7<A2, A3, A4, A5, A6, A7, A8>::asynchronous;
1795 };
1796
1797 template <typename A1, typename A2, typename A3, typename A4, typename A5,
1798           typename A6, typename A7, typename A8, typename A9>
1799 class DBusResult9 :
1800     public Result9<A1, A2, A3, A4, A5, A6, A7, A8, A9>,
1801     public DBusResult
1802 {
1803  public:
1804     DBusResult9(DBusConnection *conn,
1805                 DBusMessage *msg) :
1806         DBusResult(conn, msg)
1807     {}
1808   
1809     virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
1810     {
1811         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1812         if (!reply) {
1813             throw std::runtime_error("no DBusMessage");
1814         }
1815         append_retvals(reply, a1, a2, a3, a4, a5, a6, a7, a8, a9);
1816         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1817             throw std::runtime_error("dbus_connection_send failed");
1818         }
1819     }
1820
1821     static std::string getSignature() {
1822         return dbus_traits<A1>::getSignature() +
1823             DBusResult8<A2, A3, A4, A5, A6, A7, A8, A9>::getSignature();
1824     }
1825
1826     static const bool asynchronous =
1827         dbus_traits<A1>::asynchronous ||
1828         DBusResult8<A2, A3, A4, A5, A6, A7, A8, A9>::asynchronous;
1829 };
1830
1831 template <typename A1, typename A2, typename A3, typename A4, typename A5,
1832           typename A6, typename A7, typename A8, typename A9, typename A10>
1833 class DBusResult10 :
1834     public Result10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>,
1835     public DBusResult
1836 {
1837  public:
1838     DBusResult10(DBusConnection *conn,
1839                  DBusMessage *msg) :
1840         DBusResult(conn, msg)
1841     {}
1842   
1843     virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
1844     {
1845         DBusMessagePtr reply(g_dbus_create_reply(m_msg.get(), DBUS_TYPE_INVALID));
1846         if (!reply) {
1847             throw std::runtime_error("no DBusMessage");
1848         }
1849         append_retvals(reply, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
1850         if (!dbus_connection_send(m_conn.get(), reply.get(), NULL)) {
1851             throw std::runtime_error("dbus_connection_send failed");
1852         }
1853     }
1854
1855     static std::string getSignature() {
1856         return dbus_traits<A1>::getSignature() +
1857             DBusResult9<A2, A3, A4, A5, A6, A7, A8, A9, A10>::getSignature();
1858     }
1859
1860     static const bool asynchronous =
1861         dbus_traits<A1>::asynchronous ||
1862         DBusResult9<A2, A3, A4, A5, A6, A7, A8, A9, A10>::asynchronous;
1863 };
1864
1865 /**
1866  * A parameter which points towards one of our Result* structures.
1867  * All of the types contained in it count towards the Reply signature.
1868  * The requested Result type itself is constructed here.
1869  *
1870  * @param R      Result0, Result1<type>, ...
1871  * @param DBusR  the class implementing R
1872  */
1873 template <class R, class DBusR> struct dbus_traits_result
1874 {
1875     static std::string getType() { return DBusR::getSignature(); }
1876     static std::string getSignature() { return ""; }
1877     static std::string getReply() { return getType(); }
1878
1879     typedef boost::shared_ptr<R> host_type;
1880     typedef boost::shared_ptr<R> &arg_type;
1881     static const bool asynchronous = true;
1882
1883     static void get(DBusConnection *conn, DBusMessage *msg,
1884                     DBusMessageIter &iter, host_type &value)
1885     {
1886         value.reset(new DBusR(conn, msg));
1887     }
1888
1889     static void append(DBusMessageIter &iter, const host_type &value) {}
1890     static void append_retval(DBusMessageIter &iter, const host_type &value) {}
1891 };
1892
1893 template <>
1894 struct dbus_traits< boost::shared_ptr<Result0> > :
1895     public dbus_traits_result<Result0, DBusResult0>
1896 {};
1897 template <class A1>
1898 struct dbus_traits< boost::shared_ptr< Result1<A1> > >:
1899     public dbus_traits_result< Result1<A1>, DBusResult1<A1> >
1900 {};
1901 template <class A1, class A2>
1902 struct dbus_traits< boost::shared_ptr< Result2<A1, A2> > >:
1903     public dbus_traits_result< Result2<A1, A2>, DBusResult2<A1, A2> >
1904 {};
1905 template <class A1, class A2, class A3>
1906     struct dbus_traits< boost::shared_ptr< Result3<A1, A2, A3> > >:
1907     public dbus_traits_result< Result3<A1, A2, A3>, DBusResult3<A1, A2, A3> >
1908 {};
1909 template <class A1, class A2, class A3, class A4>
1910     struct dbus_traits< boost::shared_ptr< Result4<A1, A2, A3, A4> > >:
1911     public dbus_traits_result< Result4<A1, A2, A3, A4>, DBusResult4<A1, A2, A3, A4> >
1912 {};
1913 template <class A1, class A2, class A3, class A4, class A5>
1914     struct dbus_traits< boost::shared_ptr< Result5<A1, A2, A3, A4, A5> > >:
1915     public dbus_traits_result< Result5<A1, A2, A3, A4, A5>, DBusResult5<A1, A2, A3, A4, A5> >
1916 {};
1917 template <class A1, class A2, class A3, class A4, class A5, class A6>
1918     struct dbus_traits< boost::shared_ptr< Result6<A1, A2, A3, A4, A5, A6> > >:
1919     public dbus_traits_result< Result6<A1, A2, A3, A4, A5, A6>, DBusResult6<A1, A2, A3, A4, A5, A6> >
1920 {};
1921 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
1922     struct dbus_traits< boost::shared_ptr< Result7<A1, A2, A3, A4, A5, A6, A7> > >:
1923     public dbus_traits_result< Result7<A1, A2, A3, A4, A5, A6, A7>, DBusResult7<A1, A2, A3, A4, A5, A6, A7> >
1924 {};
1925 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
1926     struct dbus_traits< boost::shared_ptr< Result8<A1, A2, A3, A4, A5, A6, A7, A8> > >:
1927     public dbus_traits_result< Result8<A1, A2, A3, A4, A5, A6, A7, A8>, DBusResult8<A1, A2, A3, A4, A5, A6, A7, A8> >
1928 {};
1929 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
1930     struct dbus_traits< boost::shared_ptr< Result9<A1, A2, A3, A4, A5, A6, A7, A8, A9> > >:
1931     public dbus_traits_result< Result9<A1, A2, A3, A4, A5, A6, A7, A8, A9>, DBusResult9<A1, A2, A3, A4, A5, A6, A7, A8, A9> >
1932 {};
1933 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
1934     struct dbus_traits< boost::shared_ptr< Result10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> > >:
1935     public dbus_traits_result< Result10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>, DBusResult10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> >
1936 {};
1937
1938
1939 #if 0
1940 /**
1941  * Call with two parameters and one return code. All other calls are
1942  * variations of this, so this one is fully documented to explain all
1943  * tricks used in these templates. The actual code without comments is
1944  * below.
1945  */
1946 template <class R, class A1, class A2>
1947 struct MakeMethodEntry< boost::function<R (A1, A2)> >
1948 {
1949     typedef boost::function<R (A1, A2)> M;
1950
1951     // Any type a Result parameter? This can be computed at compile time.
1952     static const bool asynchronous = dbus_traits< DBusResult2<A1, A2> >::asynchronous;
1953
1954     static DBusMessage *methodFunction(DBusConnection *conn,
1955                                        DBusMessage *msg, void *data)
1956     {
1957         // all exceptions must be caught and translated into
1958         // a suitable D-Bus reply
1959         try {
1960             // Argument types might may be references or pointers.
1961             // To instantiate a variable we need the underlying
1962             // datatype, which is provided by the dbus_traits.
1963             // "typename" is necessary to tell the compiler
1964             // that host_type really is a type.
1965             typename dbus_traits<R>::host_type r;
1966             typename dbus_traits<A1>::host_type a1;
1967             typename dbus_traits<A2>::host_type a2;
1968
1969             // Extract all parameters. Because we don't now
1970             // whether a parameter is an argument or a return
1971             // value, we call get() for each of them and let
1972             // the corresponding dbus_traits decide that. Traits
1973             // for types which are plain types or const references
1974             // have a non-empty get(), whereas references are treated
1975             // as return values and have an empty get().
1976             DBusMessageIter iter;
1977             dbus_message_iter_init(msg, &iter);
1978             dbus_traits<A1>::get(conn, msg, iter, a1);
1979             dbus_traits<A2>::get(conn, msg, iter, a2);
1980
1981             // The data pointer is a pointer to a boost function,
1982             // as set up for us by make(). The compiler knows the
1983             // exact method prototype and thus can handle
1984             // call-by-value and call-by-reference correctly.
1985             r = (*static_cast<M *>(data))(a1, a2);
1986
1987             // No reply necessary? If any of the types is asking for
1988             // a Result handle, then the reply will be sent later.
1989             if (asynchronous) {
1990                 return NULL;
1991             }
1992
1993             // Now prepare the reply. As with extracting parameters,
1994             // append() is empty for those parameters where nothing
1995             // has to be done.
1996             DBusMessage *reply = dbus_message_new_method_return(msg);
1997             if (!reply)
1998                 return NULL;
1999             dbus_message_iter_init_append(reply, &iter);
2000             // We know that the return value has to be appended,
2001             // even though the trait would not normally do that
2002             // because it is a plain type => call utility function
2003             // directly.
2004             dbus_traits<R>::append_retval(iter, r);
2005             dbus_traits<A1>::append(iter, a1);
2006             dbus_traits<A2>::append(iter, a2);
2007             return reply;
2008         } catch (...) {
2009             // let handleException rethrow the exception
2010             // to determine its type
2011             return handleException(msg);
2012         }
2013     }
2014
2015     /**
2016      * The boost function doesn't have a virtual destructor.
2017      * Therefore we have to cast down to the right type M
2018      * before deleting it. The rest of the allocated data
2019      * is freed by GDBusVector.
2020      */
2021     static void destroyFunction(void *user_data)
2022     {
2023         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2024         delete static_cast<M *>(entry->method_data);
2025     }
2026
2027     /**
2028      * Creates a GDBusMethodTable entry.
2029      * The strings inside the entry are allocated
2030      * with strdup(), to be freed by GDBusVector::destroy().
2031      */
2032     GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2033     {
2034         GDBusMethodTable entry;
2035         entry.name = strdup(name);
2036         // same trick as before: only argument types
2037         // are added to the signature
2038         std::string buffer;
2039         buffer += dbus_traits<A1>::getSignature();
2040         buffer += dbus_traits<A2>::getSignature();
2041         entry.signature = strdup(buffer.c_str());
2042         // now the same for reply types
2043         buffer.clear();
2044         buffer += dbus_traits<R>::getReply();
2045         buffer += dbus_traits<A1>::getReply();
2046         buffer += dbus_traits<A2>::getReply();
2047         entry.reply = strdup(buffer.c_str());
2048         // these are the function templates above
2049         entry.function = methodFunction;
2050         entry.destroy = destroyFunction;
2051         // make sure that methodFunction has access to the boost function
2052         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2053                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2054         entry.method_data = new M(m);
2055         return entry;
2056     }
2057 };
2058 #endif // 0
2059
2060 /** ===> 10 parameters */
2061 template <class A1, class A2, class A3, class A4, class A5,
2062           class A6, class A7, class A8, class A9, class A10>
2063 struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> >
2064 {
2065     typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
2066     typedef boost::function<Mptr> M;
2067
2068     template <class I, class C> static M bind(Mptr C::*method, I instance) {
2069         // this fails because bind() only supports up to 9 parameters, including
2070         // the initial this pointer
2071         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8, _9 /* _10 */);
2072     }
2073
2074     static const bool asynchronous = dbus_traits< DBusResult10<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> >::asynchronous;
2075
2076     static DBusMessage *methodFunction(DBusConnection *conn,
2077                                        DBusMessage *msg, void *data)
2078     {
2079         try {
2080             typename dbus_traits<A1>::host_type a1;
2081             typename dbus_traits<A2>::host_type a2;
2082             typename dbus_traits<A3>::host_type a3;
2083             typename dbus_traits<A4>::host_type a4;
2084             typename dbus_traits<A5>::host_type a5;
2085             typename dbus_traits<A6>::host_type a6;
2086             typename dbus_traits<A7>::host_type a7;
2087             typename dbus_traits<A8>::host_type a8;
2088             typename dbus_traits<A9>::host_type a9;
2089             typename dbus_traits<A10>::host_type a10;
2090
2091             DBusMessageIter iter;
2092             dbus_message_iter_init(msg, &iter);
2093             dbus_traits<A1>::get(conn, msg, iter, a1);
2094             dbus_traits<A2>::get(conn, msg, iter, a2);
2095             dbus_traits<A3>::get(conn, msg, iter, a3);
2096             dbus_traits<A4>::get(conn, msg, iter, a4);
2097             dbus_traits<A5>::get(conn, msg, iter, a5);
2098             dbus_traits<A6>::get(conn, msg, iter, a6);
2099             dbus_traits<A7>::get(conn, msg, iter, a7);
2100             dbus_traits<A8>::get(conn, msg, iter, a8);
2101             dbus_traits<A9>::get(conn, msg, iter, a9);
2102             dbus_traits<A10>::get(conn, msg, iter, a10);
2103
2104             (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
2105
2106             if (asynchronous) {
2107                 return NULL;
2108             }
2109
2110             DBusMessage *reply = dbus_message_new_method_return(msg);
2111             if (!reply)
2112                 return NULL;
2113             dbus_message_iter_init_append(reply, &iter);
2114             dbus_traits<A1>::append(iter, a1);
2115             dbus_traits<A2>::append(iter, a2);
2116             dbus_traits<A3>::append(iter, a3);
2117             dbus_traits<A4>::append(iter, a4);
2118             dbus_traits<A5>::append(iter, a5);
2119             dbus_traits<A6>::append(iter, a6);
2120             dbus_traits<A7>::append(iter, a7);
2121             dbus_traits<A8>::append(iter, a8);
2122             dbus_traits<A9>::append(iter, a9);
2123             dbus_traits<A10>::append(iter, a10);
2124             return reply;
2125         } catch (...) {
2126             return handleException(msg);
2127         }
2128     }
2129
2130     static void destroyFunction(void *user_data)
2131     {
2132         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2133         delete static_cast<M *>(entry->method_data);
2134     }
2135
2136     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2137     {
2138         GDBusMethodTable entry;
2139         entry.name = strdup(name);
2140         std::string buffer;
2141         buffer += dbus_traits<A1>::getSignature();
2142         buffer += dbus_traits<A2>::getSignature();
2143         buffer += dbus_traits<A3>::getSignature();
2144         buffer += dbus_traits<A4>::getSignature();
2145         buffer += dbus_traits<A5>::getSignature();
2146         buffer += dbus_traits<A6>::getSignature();
2147         buffer += dbus_traits<A7>::getSignature();
2148         buffer += dbus_traits<A8>::getSignature();
2149         buffer += dbus_traits<A9>::getSignature();
2150         buffer += dbus_traits<A10>::getSignature();
2151         entry.signature = strdup(buffer.c_str());
2152         buffer.clear();
2153         buffer += dbus_traits<A1>::getReply();
2154         buffer += dbus_traits<A2>::getReply();
2155         buffer += dbus_traits<A3>::getReply();
2156         buffer += dbus_traits<A4>::getReply();
2157         buffer += dbus_traits<A5>::getReply();
2158         buffer += dbus_traits<A6>::getReply();
2159         buffer += dbus_traits<A7>::getReply();
2160         buffer += dbus_traits<A8>::getReply();
2161         buffer += dbus_traits<A9>::getReply();
2162         buffer += dbus_traits<A10>::getReply();
2163         entry.reply = strdup(buffer.c_str());
2164         entry.function = methodFunction;
2165         entry.destroy = destroyFunction;
2166         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2167                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2168         entry.method_data = new M(m);
2169         return entry;
2170     }
2171 };
2172
2173 /** 9 arguments, 1 return value */
2174 template <class R,
2175           class A1, class A2, class A3, class A4, class A5,
2176           class A6, class A7, class A8, class A9>
2177 struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6, A7, A8, A9)> >
2178 {
2179     typedef R (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8, A9);
2180     typedef boost::function<Mptr> M;
2181
2182     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2183         // this fails because bind() only supports up to 9 parameters, including
2184         // the initial this pointer
2185         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8, _9);
2186     }
2187
2188     static const bool asynchronous = DBusResult9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::asynchronous;
2189
2190     static DBusMessage *methodFunction(DBusConnection *conn,
2191                                        DBusMessage *msg, void *data)
2192     {
2193         try {
2194             typename dbus_traits<R>::host_type r;
2195             typename dbus_traits<A1>::host_type a1;
2196             typename dbus_traits<A2>::host_type a2;
2197             typename dbus_traits<A3>::host_type a3;
2198             typename dbus_traits<A4>::host_type a4;
2199             typename dbus_traits<A5>::host_type a5;
2200             typename dbus_traits<A6>::host_type a6;
2201             typename dbus_traits<A7>::host_type a7;
2202             typename dbus_traits<A8>::host_type a8;
2203             typename dbus_traits<A9>::host_type a9;
2204
2205             DBusMessageIter iter;
2206             dbus_message_iter_init(msg, &iter);
2207             dbus_traits<A1>::get(conn, msg, iter, a1);
2208             dbus_traits<A2>::get(conn, msg, iter, a2);
2209             dbus_traits<A3>::get(conn, msg, iter, a3);
2210             dbus_traits<A4>::get(conn, msg, iter, a4);
2211             dbus_traits<A5>::get(conn, msg, iter, a5);
2212             dbus_traits<A6>::get(conn, msg, iter, a6);
2213             dbus_traits<A7>::get(conn, msg, iter, a7);
2214             dbus_traits<A8>::get(conn, msg, iter, a8);
2215             dbus_traits<A9>::get(conn, msg, iter, a9);
2216
2217             r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8, a9);
2218
2219             if (asynchronous) {
2220                 return NULL;
2221             }
2222
2223             DBusMessage *reply = dbus_message_new_method_return(msg);
2224             if (!reply)
2225                 return NULL;
2226             dbus_message_iter_init_append(reply, &iter);
2227             dbus_traits<R>::append_retval(iter, r);
2228             dbus_traits<A1>::append(iter, a1);
2229             dbus_traits<A2>::append(iter, a2);
2230             dbus_traits<A3>::append(iter, a3);
2231             dbus_traits<A4>::append(iter, a4);
2232             dbus_traits<A5>::append(iter, a5);
2233             dbus_traits<A6>::append(iter, a6);
2234             dbus_traits<A7>::append(iter, a7);
2235             dbus_traits<A8>::append(iter, a8);
2236             dbus_traits<A9>::append(iter, a9);
2237             return reply;
2238         } catch (...) {
2239             return handleException(msg);
2240         }
2241     }
2242
2243     static void destroyFunction(void *user_data)
2244     {
2245         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2246         delete static_cast<M *>(entry->method_data);
2247     }
2248
2249     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2250     {
2251         GDBusMethodTable entry;
2252         entry.name = strdup(name);
2253         std::string buffer;
2254         buffer += dbus_traits<A1>::getSignature();
2255         buffer += dbus_traits<A2>::getSignature();
2256         buffer += dbus_traits<A3>::getSignature();
2257         buffer += dbus_traits<A4>::getSignature();
2258         buffer += dbus_traits<A5>::getSignature();
2259         buffer += dbus_traits<A6>::getSignature();
2260         buffer += dbus_traits<A7>::getSignature();
2261         buffer += dbus_traits<A8>::getSignature();
2262         buffer += dbus_traits<A9>::getSignature();
2263         entry.signature = strdup(buffer.c_str());
2264         buffer.clear();
2265         buffer += dbus_traits<R>::getReply();
2266         buffer += dbus_traits<A1>::getReply();
2267         buffer += dbus_traits<A2>::getReply();
2268         buffer += dbus_traits<A3>::getReply();
2269         buffer += dbus_traits<A4>::getReply();
2270         buffer += dbus_traits<A5>::getReply();
2271         buffer += dbus_traits<A6>::getReply();
2272         buffer += dbus_traits<A7>::getReply();
2273         buffer += dbus_traits<A8>::getReply();
2274         buffer += dbus_traits<A9>::getReply();
2275         entry.reply = strdup(buffer.c_str());
2276         entry.function = methodFunction;
2277         entry.destroy = destroyFunction;
2278         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2279                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2280         entry.method_data = new M(m);
2281         return entry;
2282     }
2283 };
2284
2285 /** ===> 9 parameters */
2286 template <class A1, class A2, class A3, class A4, class A5,
2287           class A6, class A7, class A8, class A9>
2288 struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7, A8, A9)> >
2289 {
2290     typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8, A9);
2291     typedef boost::function<Mptr> M;
2292
2293     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2294         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8, _9);
2295     }
2296
2297     static const bool asynchronous = DBusResult9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::asynchronous;
2298
2299     static DBusMessage *methodFunction(DBusConnection *conn,
2300                                        DBusMessage *msg, void *data)
2301     {
2302         try {
2303             typename dbus_traits<A1>::host_type a1;
2304             typename dbus_traits<A2>::host_type a2;
2305             typename dbus_traits<A3>::host_type a3;
2306             typename dbus_traits<A4>::host_type a4;
2307             typename dbus_traits<A5>::host_type a5;
2308             typename dbus_traits<A6>::host_type a6;
2309             typename dbus_traits<A7>::host_type a7;
2310             typename dbus_traits<A8>::host_type a8;
2311             typename dbus_traits<A9>::host_type a9;
2312
2313             DBusMessageIter iter;
2314             dbus_message_iter_init(msg, &iter);
2315             dbus_traits<A1>::get(conn, msg, iter, a1);
2316             dbus_traits<A2>::get(conn, msg, iter, a2);
2317             dbus_traits<A3>::get(conn, msg, iter, a3);
2318             dbus_traits<A4>::get(conn, msg, iter, a4);
2319             dbus_traits<A5>::get(conn, msg, iter, a5);
2320             dbus_traits<A6>::get(conn, msg, iter, a6);
2321             dbus_traits<A7>::get(conn, msg, iter, a7);
2322             dbus_traits<A8>::get(conn, msg, iter, a8);
2323             dbus_traits<A9>::get(conn, msg, iter, a9);
2324
2325             (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8, a9);
2326
2327             if (asynchronous) {
2328                 return NULL;
2329             }
2330
2331             DBusMessage *reply = dbus_message_new_method_return(msg);
2332             if (!reply)
2333                 return NULL;
2334             dbus_message_iter_init_append(reply, &iter);
2335             dbus_traits<A1>::append(iter, a1);
2336             dbus_traits<A2>::append(iter, a2);
2337             dbus_traits<A3>::append(iter, a3);
2338             dbus_traits<A4>::append(iter, a4);
2339             dbus_traits<A5>::append(iter, a5);
2340             dbus_traits<A6>::append(iter, a6);
2341             dbus_traits<A7>::append(iter, a7);
2342             dbus_traits<A8>::append(iter, a8);
2343             dbus_traits<A9>::append(iter, a9);
2344             return reply;
2345         } catch (...) {
2346             return handleException(msg);
2347         }
2348     }
2349
2350     static void destroyFunction(void *user_data)
2351     {
2352         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2353         delete static_cast<M *>(entry->method_data);
2354     }
2355
2356     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2357     {
2358         GDBusMethodTable entry;
2359         entry.name = strdup(name);
2360         std::string buffer;
2361         buffer += dbus_traits<A1>::getSignature();
2362         buffer += dbus_traits<A2>::getSignature();
2363         buffer += dbus_traits<A3>::getSignature();
2364         buffer += dbus_traits<A4>::getSignature();
2365         buffer += dbus_traits<A5>::getSignature();
2366         buffer += dbus_traits<A6>::getSignature();
2367         buffer += dbus_traits<A7>::getSignature();
2368         buffer += dbus_traits<A8>::getSignature();
2369         buffer += dbus_traits<A9>::getSignature();
2370         entry.signature = strdup(buffer.c_str());
2371         buffer.clear();
2372         buffer += dbus_traits<A1>::getReply();
2373         buffer += dbus_traits<A2>::getReply();
2374         buffer += dbus_traits<A3>::getReply();
2375         buffer += dbus_traits<A4>::getReply();
2376         buffer += dbus_traits<A5>::getReply();
2377         buffer += dbus_traits<A6>::getReply();
2378         buffer += dbus_traits<A7>::getReply();
2379         buffer += dbus_traits<A8>::getReply();
2380         buffer += dbus_traits<A9>::getReply();
2381         entry.reply = strdup(buffer.c_str());
2382         entry.function = methodFunction;
2383         entry.destroy = destroyFunction;
2384         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2385                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2386         entry.method_data = new M(m);
2387         return entry;
2388     }
2389 };
2390
2391 /** 8 arguments, 1 return value */
2392 template <class R,
2393           class A1, class A2, class A3, class A4, class A5,
2394           class A6, class A7, class A8>
2395 struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6, A7, A8)> >
2396 {
2397     typedef R (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8);
2398     typedef boost::function<Mptr> M;
2399
2400     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2401         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8);
2402     }
2403
2404     static const bool asynchronous = DBusResult8<A1, A2, A3, A4, A5, A6, A7, A8>::asynchronous;
2405
2406     static DBusMessage *methodFunction(DBusConnection *conn,
2407                                        DBusMessage *msg, void *data)
2408     {
2409         try {
2410             typename dbus_traits<R>::host_type r;
2411             typename dbus_traits<A1>::host_type a1;
2412             typename dbus_traits<A2>::host_type a2;
2413             typename dbus_traits<A3>::host_type a3;
2414             typename dbus_traits<A4>::host_type a4;
2415             typename dbus_traits<A5>::host_type a5;
2416             typename dbus_traits<A6>::host_type a6;
2417             typename dbus_traits<A7>::host_type a7;
2418             typename dbus_traits<A8>::host_type a8;
2419
2420             DBusMessageIter iter;
2421             dbus_message_iter_init(msg, &iter);
2422             dbus_traits<A1>::get(conn, msg, iter, a1);
2423             dbus_traits<A2>::get(conn, msg, iter, a2);
2424             dbus_traits<A3>::get(conn, msg, iter, a3);
2425             dbus_traits<A4>::get(conn, msg, iter, a4);
2426             dbus_traits<A5>::get(conn, msg, iter, a5);
2427             dbus_traits<A6>::get(conn, msg, iter, a6);
2428             dbus_traits<A7>::get(conn, msg, iter, a7);
2429             dbus_traits<A8>::get(conn, msg, iter, a8);
2430
2431             r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8);
2432
2433             if (asynchronous) {
2434                 return NULL;
2435             }
2436
2437             DBusMessage *reply = dbus_message_new_method_return(msg);
2438             if (!reply)
2439                 return NULL;
2440             dbus_message_iter_init_append(reply, &iter);
2441             dbus_traits<R>::append_retval(iter, r);
2442             dbus_traits<A1>::append(iter, a1);
2443             dbus_traits<A2>::append(iter, a2);
2444             dbus_traits<A3>::append(iter, a3);
2445             dbus_traits<A4>::append(iter, a4);
2446             dbus_traits<A5>::append(iter, a5);
2447             dbus_traits<A6>::append(iter, a6);
2448             dbus_traits<A7>::append(iter, a7);
2449             dbus_traits<A8>::append(iter, a8);
2450             return reply;
2451         } catch (...) {
2452             return handleException(msg);
2453         }
2454     }
2455
2456     static void destroyFunction(void *user_data)
2457     {
2458         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2459         delete static_cast<M *>(entry->method_data);
2460     }
2461
2462     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2463     {
2464         GDBusMethodTable entry;
2465         entry.name = strdup(name);
2466         std::string buffer;
2467         buffer += dbus_traits<A1>::getSignature();
2468         buffer += dbus_traits<A2>::getSignature();
2469         buffer += dbus_traits<A3>::getSignature();
2470         buffer += dbus_traits<A4>::getSignature();
2471         buffer += dbus_traits<A5>::getSignature();
2472         buffer += dbus_traits<A6>::getSignature();
2473         buffer += dbus_traits<A7>::getSignature();
2474         buffer += dbus_traits<A8>::getSignature();
2475         entry.signature = strdup(buffer.c_str());
2476         buffer.clear();
2477         buffer += dbus_traits<R>::getReply();
2478         buffer += dbus_traits<A1>::getReply();
2479         buffer += dbus_traits<A2>::getReply();
2480         buffer += dbus_traits<A3>::getReply();
2481         buffer += dbus_traits<A4>::getReply();
2482         buffer += dbus_traits<A5>::getReply();
2483         buffer += dbus_traits<A6>::getReply();
2484         buffer += dbus_traits<A7>::getReply();
2485         buffer += dbus_traits<A8>::getReply();
2486         entry.reply = strdup(buffer.c_str());
2487         entry.function = methodFunction;
2488         entry.destroy = destroyFunction;
2489         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2490                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2491         entry.method_data = new M(m);
2492         return entry;
2493     }
2494 };
2495
2496 /** ===> 8 parameters */
2497 template <class A1, class A2, class A3, class A4, class A5,
2498           class A6, class A7, class A8>
2499 struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7, A8)> >
2500 {
2501     typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7, A8);
2502     typedef boost::function<Mptr> M;
2503
2504     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2505         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8);
2506     }
2507
2508     static const bool asynchronous = DBusResult8<A1, A2, A3, A4, A5, A6, A7, A8>::asynchronous;
2509
2510     static DBusMessage *methodFunction(DBusConnection *conn,
2511                                        DBusMessage *msg, void *data)
2512     {
2513         try {
2514             typename dbus_traits<A1>::host_type a1;
2515             typename dbus_traits<A2>::host_type a2;
2516             typename dbus_traits<A3>::host_type a3;
2517             typename dbus_traits<A4>::host_type a4;
2518             typename dbus_traits<A5>::host_type a5;
2519             typename dbus_traits<A6>::host_type a6;
2520             typename dbus_traits<A7>::host_type a7;
2521             typename dbus_traits<A8>::host_type a8;
2522
2523             DBusMessageIter iter;
2524             dbus_message_iter_init(msg, &iter);
2525             dbus_traits<A1>::get(conn, msg, iter, a1);
2526             dbus_traits<A2>::get(conn, msg, iter, a2);
2527             dbus_traits<A3>::get(conn, msg, iter, a3);
2528             dbus_traits<A4>::get(conn, msg, iter, a4);
2529             dbus_traits<A5>::get(conn, msg, iter, a5);
2530             dbus_traits<A6>::get(conn, msg, iter, a6);
2531             dbus_traits<A7>::get(conn, msg, iter, a7);
2532             dbus_traits<A8>::get(conn, msg, iter, a8);
2533
2534             (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7, a8);
2535
2536             if (asynchronous) {
2537                 return NULL;
2538             }
2539
2540             DBusMessage *reply = dbus_message_new_method_return(msg);
2541             if (!reply)
2542                 return NULL;
2543             dbus_message_iter_init_append(reply, &iter);
2544             dbus_traits<A1>::append(iter, a1);
2545             dbus_traits<A2>::append(iter, a2);
2546             dbus_traits<A3>::append(iter, a3);
2547             dbus_traits<A4>::append(iter, a4);
2548             dbus_traits<A5>::append(iter, a5);
2549             dbus_traits<A6>::append(iter, a6);
2550             dbus_traits<A7>::append(iter, a7);
2551             dbus_traits<A8>::append(iter, a8);
2552             return reply;
2553         } catch (...) {
2554             return handleException(msg);
2555         }
2556     }
2557
2558     static void destroyFunction(void *user_data)
2559     {
2560         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2561         delete static_cast<M *>(entry->method_data);
2562     }
2563
2564     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2565     {
2566         GDBusMethodTable entry;
2567         entry.name = strdup(name);
2568         std::string buffer;
2569         buffer += dbus_traits<A1>::getSignature();
2570         buffer += dbus_traits<A2>::getSignature();
2571         buffer += dbus_traits<A3>::getSignature();
2572         buffer += dbus_traits<A4>::getSignature();
2573         buffer += dbus_traits<A5>::getSignature();
2574         buffer += dbus_traits<A6>::getSignature();
2575         buffer += dbus_traits<A7>::getSignature();
2576         buffer += dbus_traits<A8>::getSignature();
2577         entry.signature = strdup(buffer.c_str());
2578         buffer.clear();
2579         buffer += dbus_traits<A1>::getReply();
2580         buffer += dbus_traits<A2>::getReply();
2581         buffer += dbus_traits<A3>::getReply();
2582         buffer += dbus_traits<A4>::getReply();
2583         buffer += dbus_traits<A5>::getReply();
2584         buffer += dbus_traits<A6>::getReply();
2585         buffer += dbus_traits<A7>::getReply();
2586         buffer += dbus_traits<A8>::getReply();
2587         entry.reply = strdup(buffer.c_str());
2588         entry.function = methodFunction;
2589         entry.destroy = destroyFunction;
2590         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2591                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2592         entry.method_data = new M(m);
2593         return entry;
2594     }
2595 };
2596
2597 /** 7 arguments, 1 return value */
2598 template <class R,
2599           class A1, class A2, class A3, class A4, class A5,
2600           class A6, class A7>
2601 struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6, A7)> >
2602 {
2603     typedef R (Mptr)(A1, A2, A3, A4, A5, A6, A7);
2604     typedef boost::function<Mptr> M;
2605
2606     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2607         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7);
2608     }
2609
2610     static const bool asynchronous = DBusResult7<A1, A2, A3, A4, A5, A6, A7>::asynchronous;
2611
2612     static DBusMessage *methodFunction(DBusConnection *conn,
2613                                        DBusMessage *msg, void *data)
2614     {
2615         try {
2616             typename dbus_traits<R>::host_type r;
2617             typename dbus_traits<A1>::host_type a1;
2618             typename dbus_traits<A2>::host_type a2;
2619             typename dbus_traits<A3>::host_type a3;
2620             typename dbus_traits<A4>::host_type a4;
2621             typename dbus_traits<A5>::host_type a5;
2622             typename dbus_traits<A6>::host_type a6;
2623             typename dbus_traits<A7>::host_type a7;
2624
2625             DBusMessageIter iter;
2626             dbus_message_iter_init(msg, &iter);
2627             dbus_traits<A1>::get(conn, msg, iter, a1);
2628             dbus_traits<A2>::get(conn, msg, iter, a2);
2629             dbus_traits<A3>::get(conn, msg, iter, a3);
2630             dbus_traits<A4>::get(conn, msg, iter, a4);
2631             dbus_traits<A5>::get(conn, msg, iter, a5);
2632             dbus_traits<A6>::get(conn, msg, iter, a6);
2633             dbus_traits<A7>::get(conn, msg, iter, a7);
2634
2635             r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7);
2636
2637             if (asynchronous) {
2638                 return NULL;
2639             }
2640
2641             DBusMessage *reply = dbus_message_new_method_return(msg);
2642             if (!reply)
2643                 return NULL;
2644             dbus_message_iter_init_append(reply, &iter);
2645             dbus_traits<R>::append_retval(iter, r);
2646             dbus_traits<A1>::append(iter, a1);
2647             dbus_traits<A2>::append(iter, a2);
2648             dbus_traits<A3>::append(iter, a3);
2649             dbus_traits<A4>::append(iter, a4);
2650             dbus_traits<A5>::append(iter, a5);
2651             dbus_traits<A6>::append(iter, a6);
2652             dbus_traits<A7>::append(iter, a7);
2653             return reply;
2654         } catch (...) {
2655             return handleException(msg);
2656         }
2657     }
2658
2659     static void destroyFunction(void *user_data)
2660     {
2661         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2662         delete static_cast<M *>(entry->method_data);
2663     }
2664
2665     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2666     {
2667         GDBusMethodTable entry;
2668         entry.name = strdup(name);
2669         std::string buffer;
2670         buffer += dbus_traits<A1>::getSignature();
2671         buffer += dbus_traits<A2>::getSignature();
2672         buffer += dbus_traits<A3>::getSignature();
2673         buffer += dbus_traits<A4>::getSignature();
2674         buffer += dbus_traits<A5>::getSignature();
2675         buffer += dbus_traits<A6>::getSignature();
2676         buffer += dbus_traits<A7>::getSignature();
2677         entry.signature = strdup(buffer.c_str());
2678         buffer.clear();
2679         buffer += dbus_traits<R>::getReply();
2680         buffer += dbus_traits<A1>::getReply();
2681         buffer += dbus_traits<A2>::getReply();
2682         buffer += dbus_traits<A3>::getReply();
2683         buffer += dbus_traits<A4>::getReply();
2684         buffer += dbus_traits<A5>::getReply();
2685         buffer += dbus_traits<A6>::getReply();
2686         buffer += dbus_traits<A7>::getReply();
2687         entry.reply = strdup(buffer.c_str());
2688         entry.function = methodFunction;
2689         entry.destroy = destroyFunction;
2690         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2691                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2692         entry.method_data = new M(m);
2693         return entry;
2694     }
2695 };
2696
2697 /** ===> 7 parameters */
2698 template <class A1, class A2, class A3, class A4, class A5,
2699           class A6, class A7>
2700 struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6, A7)> >
2701 {
2702     typedef void (Mptr)(A1, A2, A3, A4, A5, A6, A7);
2703     typedef boost::function<Mptr> M;
2704
2705     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2706         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7);
2707     }
2708
2709     static const bool asynchronous = DBusResult7<A1, A2, A3, A4, A5, A6, A7>::asynchronous;
2710
2711     static DBusMessage *methodFunction(DBusConnection *conn,
2712                                        DBusMessage *msg, void *data)
2713     {
2714         try {
2715             typename dbus_traits<A1>::host_type a1;
2716             typename dbus_traits<A2>::host_type a2;
2717             typename dbus_traits<A3>::host_type a3;
2718             typename dbus_traits<A4>::host_type a4;
2719             typename dbus_traits<A5>::host_type a5;
2720             typename dbus_traits<A6>::host_type a6;
2721             typename dbus_traits<A7>::host_type a7;
2722
2723             DBusMessageIter iter;
2724             dbus_message_iter_init(msg, &iter);
2725             dbus_traits<A1>::get(conn, msg, iter, a1);
2726             dbus_traits<A2>::get(conn, msg, iter, a2);
2727             dbus_traits<A3>::get(conn, msg, iter, a3);
2728             dbus_traits<A4>::get(conn, msg, iter, a4);
2729             dbus_traits<A5>::get(conn, msg, iter, a5);
2730             dbus_traits<A6>::get(conn, msg, iter, a6);
2731             dbus_traits<A7>::get(conn, msg, iter, a7);
2732
2733             (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6, a7);
2734
2735             if (asynchronous) {
2736                 return NULL;
2737             }
2738
2739             DBusMessage *reply = dbus_message_new_method_return(msg);
2740             if (!reply)
2741                 return NULL;
2742             dbus_message_iter_init_append(reply, &iter);
2743             dbus_traits<A1>::append(iter, a1);
2744             dbus_traits<A2>::append(iter, a2);
2745             dbus_traits<A3>::append(iter, a3);
2746             dbus_traits<A4>::append(iter, a4);
2747             dbus_traits<A5>::append(iter, a5);
2748             dbus_traits<A6>::append(iter, a6);
2749             dbus_traits<A7>::append(iter, a7);
2750             return reply;
2751         } catch (...) {
2752             return handleException(msg);
2753         }
2754     }
2755
2756     static void destroyFunction(void *user_data)
2757     {
2758         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2759         delete static_cast<M *>(entry->method_data);
2760     }
2761
2762     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2763     {
2764         GDBusMethodTable entry;
2765         entry.name = strdup(name);
2766         std::string buffer;
2767         buffer += dbus_traits<A1>::getSignature();
2768         buffer += dbus_traits<A2>::getSignature();
2769         buffer += dbus_traits<A3>::getSignature();
2770         buffer += dbus_traits<A4>::getSignature();
2771         buffer += dbus_traits<A5>::getSignature();
2772         buffer += dbus_traits<A6>::getSignature();
2773         buffer += dbus_traits<A7>::getSignature();
2774         entry.signature = strdup(buffer.c_str());
2775         buffer.clear();
2776         buffer += dbus_traits<A1>::getReply();
2777         buffer += dbus_traits<A2>::getReply();
2778         buffer += dbus_traits<A3>::getReply();
2779         buffer += dbus_traits<A4>::getReply();
2780         buffer += dbus_traits<A5>::getReply();
2781         buffer += dbus_traits<A6>::getReply();
2782         buffer += dbus_traits<A7>::getReply();
2783         entry.reply = strdup(buffer.c_str());
2784         entry.function = methodFunction;
2785         entry.destroy = destroyFunction;
2786         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2787                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2788         entry.method_data = new M(m);
2789         return entry;
2790     }
2791 };
2792
2793 /** 6 arguments, 1 return value */
2794 template <class R,
2795           class A1, class A2, class A3, class A4, class A5,
2796           class A6>
2797 struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5, A6)> >
2798 {
2799     typedef R (Mptr)(A1, A2, A3, A4, A5, A6);
2800     typedef boost::function<Mptr> M;
2801
2802     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2803         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6);
2804     }
2805
2806     static const bool asynchronous = DBusResult6<A1, A2, A3, A4, A5, A6>::asynchronous;
2807
2808     static DBusMessage *methodFunction(DBusConnection *conn,
2809                                        DBusMessage *msg, void *data)
2810     {
2811         try {
2812             typename dbus_traits<R>::host_type r;
2813             typename dbus_traits<A1>::host_type a1;
2814             typename dbus_traits<A2>::host_type a2;
2815             typename dbus_traits<A3>::host_type a3;
2816             typename dbus_traits<A4>::host_type a4;
2817             typename dbus_traits<A5>::host_type a5;
2818             typename dbus_traits<A6>::host_type a6;
2819
2820             DBusMessageIter iter;
2821             dbus_message_iter_init(msg, &iter);
2822             dbus_traits<A1>::get(conn, msg, iter, a1);
2823             dbus_traits<A2>::get(conn, msg, iter, a2);
2824             dbus_traits<A3>::get(conn, msg, iter, a3);
2825             dbus_traits<A4>::get(conn, msg, iter, a4);
2826             dbus_traits<A5>::get(conn, msg, iter, a5);
2827             dbus_traits<A6>::get(conn, msg, iter, a6);
2828
2829             r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6);
2830
2831             if (asynchronous) {
2832                 return NULL;
2833             }
2834
2835             DBusMessage *reply = dbus_message_new_method_return(msg);
2836             if (!reply)
2837                 return NULL;
2838             dbus_message_iter_init_append(reply, &iter);
2839             dbus_traits<R>::append_retval(iter, r);
2840             dbus_traits<A1>::append(iter, a1);
2841             dbus_traits<A2>::append(iter, a2);
2842             dbus_traits<A3>::append(iter, a3);
2843             dbus_traits<A4>::append(iter, a4);
2844             dbus_traits<A5>::append(iter, a5);
2845             dbus_traits<A6>::append(iter, a6);
2846             return reply;
2847         } catch (...) {
2848             return handleException(msg);
2849         }
2850     }
2851
2852     static void destroyFunction(void *user_data)
2853     {
2854         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2855         delete static_cast<M *>(entry->method_data);
2856     }
2857
2858     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2859     {
2860         GDBusMethodTable entry;
2861         entry.name = strdup(name);
2862         std::string buffer;
2863         buffer += dbus_traits<A1>::getSignature();
2864         buffer += dbus_traits<A2>::getSignature();
2865         buffer += dbus_traits<A3>::getSignature();
2866         buffer += dbus_traits<A4>::getSignature();
2867         buffer += dbus_traits<A5>::getSignature();
2868         buffer += dbus_traits<A6>::getSignature();
2869         entry.signature = strdup(buffer.c_str());
2870         buffer.clear();
2871         buffer += dbus_traits<R>::getReply();
2872         buffer += dbus_traits<A1>::getReply();
2873         buffer += dbus_traits<A2>::getReply();
2874         buffer += dbus_traits<A3>::getReply();
2875         buffer += dbus_traits<A4>::getReply();
2876         buffer += dbus_traits<A5>::getReply();
2877         buffer += dbus_traits<A6>::getReply();
2878         entry.reply = strdup(buffer.c_str());
2879         entry.function = methodFunction;
2880         entry.destroy = destroyFunction;
2881         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2882                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2883         entry.method_data = new M(m);
2884         return entry;
2885     }
2886 };
2887
2888 /** ===> 6 parameters */
2889 template <class A1, class A2, class A3, class A4, class A5,
2890           class A6>
2891 struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5, A6)> >
2892 {
2893     typedef void (Mptr)(A1, A2, A3, A4, A5, A6);
2894     typedef boost::function<Mptr> M;
2895
2896     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2897         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6);
2898     }
2899
2900     static const bool asynchronous = DBusResult6<A1, A2, A3, A4, A5, A6>::asynchronous;
2901
2902     static DBusMessage *methodFunction(DBusConnection *conn,
2903                                        DBusMessage *msg, void *data)
2904     {
2905         try {
2906             typename dbus_traits<A1>::host_type a1;
2907             typename dbus_traits<A2>::host_type a2;
2908             typename dbus_traits<A3>::host_type a3;
2909             typename dbus_traits<A4>::host_type a4;
2910             typename dbus_traits<A5>::host_type a5;
2911             typename dbus_traits<A6>::host_type a6;
2912
2913             DBusMessageIter iter;
2914             dbus_message_iter_init(msg, &iter);
2915             dbus_traits<A1>::get(conn, msg, iter, a1);
2916             dbus_traits<A2>::get(conn, msg, iter, a2);
2917             dbus_traits<A3>::get(conn, msg, iter, a3);
2918             dbus_traits<A4>::get(conn, msg, iter, a4);
2919             dbus_traits<A5>::get(conn, msg, iter, a5);
2920             dbus_traits<A6>::get(conn, msg, iter, a6);
2921
2922             (*static_cast<M *>(data))(a1, a2, a3, a4, a5, a6);
2923
2924             if (asynchronous) {
2925                 return NULL;
2926             }
2927
2928             DBusMessage *reply = dbus_message_new_method_return(msg);
2929             if (!reply)
2930                 return NULL;
2931             dbus_message_iter_init_append(reply, &iter);
2932             dbus_traits<A1>::append(iter, a1);
2933             dbus_traits<A2>::append(iter, a2);
2934             dbus_traits<A3>::append(iter, a3);
2935             dbus_traits<A4>::append(iter, a4);
2936             dbus_traits<A5>::append(iter, a5);
2937             dbus_traits<A6>::append(iter, a6);
2938             return reply;
2939         } catch (...) {
2940             return handleException(msg);
2941         }
2942     }
2943     static void destroyFunction(void *user_data)
2944     {
2945         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
2946         delete static_cast<M *>(entry->method_data);
2947     }
2948
2949     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
2950     {
2951         GDBusMethodTable entry;
2952         entry.name = strdup(name);
2953         std::string buffer;
2954         buffer += dbus_traits<A1>::getSignature();
2955         buffer += dbus_traits<A2>::getSignature();
2956         buffer += dbus_traits<A3>::getSignature();
2957         buffer += dbus_traits<A4>::getSignature();
2958         buffer += dbus_traits<A5>::getSignature();
2959         buffer += dbus_traits<A6>::getSignature();
2960         entry.signature = strdup(buffer.c_str());
2961         buffer.clear();
2962         buffer += dbus_traits<A1>::getReply();
2963         buffer += dbus_traits<A2>::getReply();
2964         buffer += dbus_traits<A3>::getReply();
2965         buffer += dbus_traits<A4>::getReply();
2966         buffer += dbus_traits<A5>::getReply();
2967         buffer += dbus_traits<A6>::getReply();
2968         entry.reply = strdup(buffer.c_str());
2969         entry.function = methodFunction;
2970         entry.destroy = destroyFunction;
2971         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
2972                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
2973         entry.method_data = new M(m);
2974         return entry;
2975     }
2976 };
2977
2978 /** 5 arguments, 1 return value */
2979 template <class R,
2980           class A1, class A2, class A3, class A4, class A5>
2981 struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4, A5)> >
2982 {
2983     typedef R (Mptr)(A1, A2, A3, A4, A5);
2984     typedef boost::function<Mptr> M;
2985
2986     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
2987         return boost::bind(method, instance, _1, _2, _3, _4, _5);
2988     }
2989
2990     static const bool asynchronous = DBusResult5<A1, A2, A3, A4, A5>::asynchronous;
2991
2992     static DBusMessage *methodFunction(DBusConnection *conn,
2993                                        DBusMessage *msg, void *data)
2994     {
2995         try {
2996             typename dbus_traits<R>::host_type r;
2997             typename dbus_traits<A1>::host_type a1;
2998             typename dbus_traits<A2>::host_type a2;
2999             typename dbus_traits<A3>::host_type a3;
3000             typename dbus_traits<A4>::host_type a4;
3001             typename dbus_traits<A5>::host_type a5;
3002
3003             DBusMessageIter iter;
3004             dbus_message_iter_init(msg, &iter);
3005             dbus_traits<A1>::get(conn, msg, iter, a1);
3006             dbus_traits<A2>::get(conn, msg, iter, a2);
3007             dbus_traits<A3>::get(conn, msg, iter, a3);
3008             dbus_traits<A4>::get(conn, msg, iter, a4);
3009             dbus_traits<A5>::get(conn, msg, iter, a5);
3010
3011             r = (*static_cast<M *>(data))(a1, a2, a3, a4, a5);
3012
3013             if (asynchronous) {
3014                 return NULL;
3015             }
3016
3017             DBusMessage *reply = dbus_message_new_method_return(msg);
3018             if (!reply)
3019                 return NULL;
3020             dbus_message_iter_init_append(reply, &iter);
3021             dbus_traits<R>::append_retval(iter, r);
3022             dbus_traits<A1>::append(iter, a1);
3023             dbus_traits<A2>::append(iter, a2);
3024             dbus_traits<A3>::append(iter, a3);
3025             dbus_traits<A4>::append(iter, a4);
3026             dbus_traits<A5>::append(iter, a5);
3027             return reply;
3028         } catch (...) {
3029             return handleException(msg);
3030         }
3031     }
3032
3033     static void destroyFunction(void *user_data)
3034     {
3035         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3036         delete static_cast<M *>(entry->method_data);
3037     }
3038
3039     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3040     {
3041         GDBusMethodTable entry;
3042         entry.name = strdup(name);
3043         std::string buffer;
3044         buffer += dbus_traits<A1>::getSignature();
3045         buffer += dbus_traits<A2>::getSignature();
3046         buffer += dbus_traits<A3>::getSignature();
3047         buffer += dbus_traits<A4>::getSignature();
3048         buffer += dbus_traits<A5>::getSignature();
3049         entry.signature = strdup(buffer.c_str());
3050         buffer.clear();
3051         buffer += dbus_traits<R>::getReply();
3052         buffer += dbus_traits<A1>::getReply();
3053         buffer += dbus_traits<A2>::getReply();
3054         buffer += dbus_traits<A3>::getReply();
3055         buffer += dbus_traits<A4>::getReply();
3056         buffer += dbus_traits<A5>::getReply();
3057         entry.reply = strdup(buffer.c_str());
3058         entry.function = methodFunction;
3059         entry.destroy = destroyFunction;
3060         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3061                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3062         entry.method_data = new M(m);
3063         return entry;
3064     }
3065 };
3066
3067 /** ===> 5 parameters */
3068 template <class A1, class A2, class A3, class A4, class A5>
3069 struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4, A5)> >
3070 {
3071     typedef void (Mptr)(A1, A2, A3, A4, A5);
3072     typedef boost::function<Mptr> M;
3073
3074     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3075         return boost::bind(method, instance, _1, _2, _3, _4, _5, _6, _7, _8);
3076     }
3077
3078     static const bool asynchronous = DBusResult5<A1, A2, A3, A4, A5>::asynchronous;
3079
3080     static DBusMessage *methodFunction(DBusConnection *conn,
3081                                        DBusMessage *msg, void *data)
3082     {
3083         try {
3084             typename dbus_traits<A1>::host_type a1;
3085             typename dbus_traits<A2>::host_type a2;
3086             typename dbus_traits<A3>::host_type a3;
3087             typename dbus_traits<A4>::host_type a4;
3088             typename dbus_traits<A5>::host_type a5;
3089
3090             DBusMessageIter iter;
3091             dbus_message_iter_init(msg, &iter);
3092             dbus_traits<A1>::get(conn, msg, iter, a1);
3093             dbus_traits<A2>::get(conn, msg, iter, a2);
3094             dbus_traits<A3>::get(conn, msg, iter, a3);
3095             dbus_traits<A4>::get(conn, msg, iter, a4);
3096             dbus_traits<A5>::get(conn, msg, iter, a5);
3097
3098             (*static_cast<M *>(data))(a1, a2, a3, a4, a5);
3099
3100             if (asynchronous) {
3101                 return NULL;
3102             }
3103
3104             DBusMessage *reply = dbus_message_new_method_return(msg);
3105             if (!reply)
3106                 return NULL;
3107             dbus_message_iter_init_append(reply, &iter);
3108             dbus_traits<A1>::append(iter, a1);
3109             dbus_traits<A2>::append(iter, a2);
3110             dbus_traits<A3>::append(iter, a3);
3111             dbus_traits<A4>::append(iter, a4);
3112             dbus_traits<A5>::append(iter, a5);
3113             return reply;
3114         } catch (...) {
3115             return handleException(msg);
3116         }
3117     }
3118
3119     static void destroyFunction(void *user_data)
3120     {
3121         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3122         delete static_cast<M *>(entry->method_data);
3123     }
3124
3125     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3126     {
3127         GDBusMethodTable entry;
3128         entry.name = strdup(name);
3129         std::string buffer;
3130         buffer += dbus_traits<A1>::getSignature();
3131         buffer += dbus_traits<A2>::getSignature();
3132         buffer += dbus_traits<A3>::getSignature();
3133         buffer += dbus_traits<A4>::getSignature();
3134         buffer += dbus_traits<A5>::getSignature();
3135         entry.signature = strdup(buffer.c_str());
3136         buffer.clear();
3137         buffer += dbus_traits<A1>::getReply();
3138         buffer += dbus_traits<A2>::getReply();
3139         buffer += dbus_traits<A3>::getReply();
3140         buffer += dbus_traits<A4>::getReply();
3141         buffer += dbus_traits<A5>::getReply();
3142         entry.reply = strdup(buffer.c_str());
3143         entry.function = methodFunction;
3144         entry.destroy = destroyFunction;
3145         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3146                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3147         entry.method_data = new M(m);
3148         return entry;
3149     }
3150 };
3151
3152 /** 4 arguments, 1 return value */
3153 template <class R,
3154           class A1, class A2, class A3, class A4>
3155 struct MakeMethodEntry< boost::function<R (A1, A2, A3, A4)> >
3156 {
3157     typedef R (Mptr)(A1, A2, A3, A4);
3158     typedef boost::function<Mptr> M;
3159
3160     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3161         return boost::bind(method, instance, _1, _2, _3, _4);
3162     }
3163
3164     static const bool asynchronous = DBusResult4<A1, A2, A3, A4>::asynchronous;
3165
3166     static DBusMessage *methodFunction(DBusConnection *conn,
3167                                        DBusMessage *msg, void *data)
3168     {
3169         try {
3170             typename dbus_traits<R>::host_type r;
3171             typename dbus_traits<A1>::host_type a1;
3172             typename dbus_traits<A2>::host_type a2;
3173             typename dbus_traits<A3>::host_type a3;
3174             typename dbus_traits<A4>::host_type a4;
3175
3176             DBusMessageIter iter;
3177             dbus_message_iter_init(msg, &iter);
3178             dbus_traits<A1>::get(conn, msg, iter, a1);
3179             dbus_traits<A2>::get(conn, msg, iter, a2);
3180             dbus_traits<A3>::get(conn, msg, iter, a3);
3181             dbus_traits<A4>::get(conn, msg, iter, a4);
3182
3183             r = (*static_cast<M *>(data))(a1, a2, a3, a4);
3184
3185             if (asynchronous) {
3186                 return NULL;
3187             }
3188
3189             DBusMessage *reply = dbus_message_new_method_return(msg);
3190             if (!reply)
3191                 return NULL;
3192             dbus_message_iter_init_append(reply, &iter);
3193             dbus_traits<R>::append_retval(iter, r);
3194             dbus_traits<A1>::append(iter, a1);
3195             dbus_traits<A2>::append(iter, a2);
3196             dbus_traits<A3>::append(iter, a3);
3197             dbus_traits<A4>::append(iter, a4);
3198             return reply;
3199         } catch (...) {
3200             return handleException(msg);
3201         }
3202     }
3203
3204     static void destroyFunction(void *user_data)
3205     {
3206         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3207         delete static_cast<M *>(entry->method_data);
3208     }
3209
3210     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3211     {
3212         GDBusMethodTable entry;
3213         entry.name = strdup(name);
3214         std::string buffer;
3215         buffer += dbus_traits<A1>::getSignature();
3216         buffer += dbus_traits<A2>::getSignature();
3217         buffer += dbus_traits<A3>::getSignature();
3218         buffer += dbus_traits<A4>::getSignature();
3219         entry.signature = strdup(buffer.c_str());
3220         buffer.clear();
3221         buffer += dbus_traits<R>::getReply();
3222         buffer += dbus_traits<A1>::getReply();
3223         buffer += dbus_traits<A2>::getReply();
3224         buffer += dbus_traits<A3>::getReply();
3225         buffer += dbus_traits<A4>::getReply();
3226         entry.reply = strdup(buffer.c_str());
3227         entry.function = methodFunction;
3228         entry.destroy = destroyFunction;
3229         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3230                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3231         entry.method_data = new M(m);
3232         return entry;
3233     }
3234 };
3235
3236 /** ===> 4 parameters */
3237 template <class A1, class A2, class A3, class A4>
3238 struct MakeMethodEntry< boost::function<void (A1, A2, A3, A4)> >
3239 {
3240     typedef void (Mptr)(A1, A2, A3, A4);
3241     typedef boost::function<Mptr> M;
3242
3243     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3244         return boost::bind(method, instance, _1, _2, _3, _4);
3245     }
3246
3247     static const bool asynchronous = DBusResult4<A1, A2, A3, A4>::asynchronous;
3248
3249     static DBusMessage *methodFunction(DBusConnection *conn,
3250                                        DBusMessage *msg, void *data)
3251     {
3252         try {
3253             typename dbus_traits<A1>::host_type a1;
3254             typename dbus_traits<A2>::host_type a2;
3255             typename dbus_traits<A3>::host_type a3;
3256             typename dbus_traits<A4>::host_type a4;
3257
3258             DBusMessageIter iter;
3259             dbus_message_iter_init(msg, &iter);
3260             dbus_traits<A1>::get(conn, msg, iter, a1);
3261             dbus_traits<A2>::get(conn, msg, iter, a2);
3262             dbus_traits<A3>::get(conn, msg, iter, a3);
3263             dbus_traits<A4>::get(conn, msg, iter, a4);
3264
3265             (*static_cast<M *>(data))(a1, a2, a3, a4);
3266
3267             if (asynchronous) {
3268                 return NULL;
3269             }
3270
3271             DBusMessage *reply = dbus_message_new_method_return(msg);
3272             if (!reply)
3273                 return NULL;
3274             dbus_message_iter_init_append(reply, &iter);
3275             dbus_traits<A1>::append(iter, a1);
3276             dbus_traits<A2>::append(iter, a2);
3277             dbus_traits<A3>::append(iter, a3);
3278             dbus_traits<A4>::append(iter, a4);
3279             return reply;
3280         } catch (...) {
3281             return handleException(msg);
3282         }
3283     }
3284
3285     static void destroyFunction(void *user_data)
3286     {
3287         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3288         delete static_cast<M *>(entry->method_data);
3289     }
3290
3291     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3292     {
3293         GDBusMethodTable entry;
3294         entry.name = strdup(name);
3295         std::string buffer;
3296         buffer += dbus_traits<A1>::getSignature();
3297         buffer += dbus_traits<A2>::getSignature();
3298         buffer += dbus_traits<A3>::getSignature();
3299         buffer += dbus_traits<A4>::getSignature();
3300         entry.signature = strdup(buffer.c_str());
3301         buffer.clear();
3302         buffer += dbus_traits<A1>::getReply();
3303         buffer += dbus_traits<A2>::getReply();
3304         buffer += dbus_traits<A3>::getReply();
3305         buffer += dbus_traits<A4>::getReply();
3306         entry.reply = strdup(buffer.c_str());
3307         entry.function = methodFunction;
3308         entry.destroy = destroyFunction;
3309         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3310                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3311         entry.method_data = new M(m);
3312         return entry;
3313     }
3314 };
3315
3316 /** 3 arguments, 1 return value */
3317 template <class R,
3318           class A1, class A2, class A3>
3319 struct MakeMethodEntry< boost::function<R (A1, A2, A3)> >
3320 {
3321     typedef R (Mptr)(A1, A2, A3);
3322     typedef boost::function<Mptr> M;
3323
3324     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3325         return boost::bind(method, instance, _1, _2, _3);
3326     }
3327
3328     static const bool asynchronous = DBusResult3<A1, A2, A3>::asynchronous;
3329
3330     static DBusMessage *methodFunction(DBusConnection *conn,
3331                                        DBusMessage *msg, void *data)
3332     {
3333         try {
3334             typename dbus_traits<R>::host_type r;
3335             typename dbus_traits<A1>::host_type a1;
3336             typename dbus_traits<A2>::host_type a2;
3337             typename dbus_traits<A3>::host_type a3;
3338
3339             DBusMessageIter iter;
3340             dbus_message_iter_init(msg, &iter);
3341             dbus_traits<A1>::get(conn, msg, iter, a1);
3342             dbus_traits<A2>::get(conn, msg, iter, a2);
3343             dbus_traits<A3>::get(conn, msg, iter, a3);
3344
3345             r = (*static_cast<M *>(data))(a1, a2, a3);
3346
3347             if (asynchronous) {
3348                 return NULL;
3349             }
3350
3351             DBusMessage *reply = dbus_message_new_method_return(msg);
3352             if (!reply)
3353                 return NULL;
3354             dbus_message_iter_init_append(reply, &iter);
3355             dbus_traits<R>::append_retval(iter, r);
3356             dbus_traits<A1>::append(iter, a1);
3357             dbus_traits<A2>::append(iter, a2);
3358             dbus_traits<A3>::append(iter, a3);
3359             return reply;
3360         } catch (...) {
3361             return handleException(msg);
3362         }
3363     }
3364
3365     static void destroyFunction(void *user_data)
3366     {
3367         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3368         delete static_cast<M *>(entry->method_data);
3369     }
3370
3371     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3372     {
3373         GDBusMethodTable entry;
3374         entry.name = strdup(name);
3375         std::string buffer;
3376         buffer += dbus_traits<A1>::getSignature();
3377         buffer += dbus_traits<A2>::getSignature();
3378         buffer += dbus_traits<A3>::getSignature();
3379         entry.signature = strdup(buffer.c_str());
3380         buffer.clear();
3381         buffer += dbus_traits<R>::getReply();
3382         buffer += dbus_traits<A1>::getReply();
3383         buffer += dbus_traits<A2>::getReply();
3384         buffer += dbus_traits<A3>::getReply();
3385         entry.reply = strdup(buffer.c_str());
3386         entry.function = methodFunction;
3387         entry.destroy = destroyFunction;
3388         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3389                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3390         entry.method_data = new M(m);
3391         return entry;
3392     }
3393 };
3394
3395 /** ===> 3 parameters */
3396 template <class A1, class A2, class A3>
3397 struct MakeMethodEntry< boost::function<void (A1, A2, A3)> >
3398 {
3399     typedef void (Mptr)(A1, A2, A3);
3400     typedef boost::function<Mptr> M;
3401
3402     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3403         return boost::bind(method, instance, _1, _2, _3);
3404     }
3405
3406     static const bool asynchronous = DBusResult3<A1, A2, A3>::asynchronous;
3407
3408     static DBusMessage *methodFunction(DBusConnection *conn,
3409                                        DBusMessage *msg, void *data)
3410     {
3411         try {
3412             typename dbus_traits<A1>::host_type a1;
3413             typename dbus_traits<A2>::host_type a2;
3414             typename dbus_traits<A3>::host_type a3;
3415
3416             DBusMessageIter iter;
3417             dbus_message_iter_init(msg, &iter);
3418             dbus_traits<A1>::get(conn, msg, iter, a1);
3419             dbus_traits<A2>::get(conn, msg, iter, a2);
3420             dbus_traits<A3>::get(conn, msg, iter, a3);
3421
3422             (*static_cast<M *>(data))(a1, a2, a3);
3423
3424             if (asynchronous) {
3425                 return NULL;
3426             }
3427
3428             DBusMessage *reply = dbus_message_new_method_return(msg);
3429             if (!reply)
3430                 return NULL;
3431             dbus_message_iter_init_append(reply, &iter);
3432             dbus_traits<A1>::append(iter, a1);
3433             dbus_traits<A2>::append(iter, a2);
3434             dbus_traits<A3>::append(iter, a3);
3435             return reply;
3436         } catch (...) {
3437             return handleException(msg);
3438         }
3439     }
3440
3441     static void destroyFunction(void *user_data)
3442     {
3443         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3444         delete static_cast<M *>(entry->method_data);
3445     }
3446
3447     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3448     {
3449         GDBusMethodTable entry;
3450         entry.name = strdup(name);
3451         std::string buffer;
3452         buffer += dbus_traits<A1>::getSignature();
3453         buffer += dbus_traits<A2>::getSignature();
3454         buffer += dbus_traits<A3>::getSignature();
3455         entry.signature = strdup(buffer.c_str());
3456         buffer.clear();
3457         buffer += dbus_traits<A1>::getReply();
3458         buffer += dbus_traits<A2>::getReply();
3459         buffer += dbus_traits<A3>::getReply();
3460         entry.reply = strdup(buffer.c_str());
3461         entry.function = methodFunction;
3462         entry.destroy = destroyFunction;
3463         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3464                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3465         entry.method_data = new M(m);
3466         return entry;
3467     }
3468 };
3469
3470 /** 2 arguments, 1 return value */
3471 template <class R,
3472           class A1, class A2>
3473 struct MakeMethodEntry< boost::function<R (A1, A2)> >
3474 {
3475     typedef R (Mptr)(A1, A2);
3476     typedef boost::function<Mptr> M;
3477
3478     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3479         return boost::bind(method, instance, _1, _2);
3480     }
3481
3482     static const bool asynchronous = DBusResult2<A1, A2>::asynchronous;
3483
3484     static DBusMessage *methodFunction(DBusConnection *conn,
3485                                        DBusMessage *msg, void *data)
3486     {
3487         try {
3488             typename dbus_traits<R>::host_type r;
3489             typename dbus_traits<A1>::host_type a1;
3490             typename dbus_traits<A2>::host_type a2;
3491
3492             DBusMessageIter iter;
3493             dbus_message_iter_init(msg, &iter);
3494             dbus_traits<A1>::get(conn, msg, iter, a1);
3495             dbus_traits<A2>::get(conn, msg, iter, a2);
3496
3497             r = (*static_cast<M *>(data))(a1, a2);
3498
3499             if (asynchronous) {
3500                 return NULL;
3501             }
3502
3503             DBusMessage *reply = dbus_message_new_method_return(msg);
3504             if (!reply)
3505                 return NULL;
3506             dbus_message_iter_init_append(reply, &iter);
3507             dbus_traits<R>::append_retval(iter, r);
3508             dbus_traits<A1>::append(iter, a1);
3509             dbus_traits<A2>::append(iter, a2);
3510             return reply;
3511         } catch (...) {
3512             return handleException(msg);
3513         }
3514     }
3515
3516     static void destroyFunction(void *user_data)
3517     {
3518         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3519         delete static_cast<M *>(entry->method_data);
3520     }
3521
3522     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3523     {
3524         GDBusMethodTable entry;
3525         entry.name = strdup(name);
3526         std::string buffer;
3527         buffer += dbus_traits<A1>::getSignature();
3528         buffer += dbus_traits<A2>::getSignature();
3529         entry.signature = strdup(buffer.c_str());
3530         buffer.clear();
3531         buffer += dbus_traits<R>::getReply();
3532         buffer += dbus_traits<A1>::getReply();
3533         buffer += dbus_traits<A2>::getReply();
3534         entry.reply = strdup(buffer.c_str());
3535         entry.function = methodFunction;
3536         entry.destroy = destroyFunction;
3537         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3538                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3539         entry.method_data = new M(m);
3540         return entry;
3541     }
3542 };
3543
3544 /** ===> 2 parameters */
3545 template <class A1, class A2>
3546 struct MakeMethodEntry< boost::function<void (A1, A2)> >
3547 {
3548     typedef void (Mptr)(A1, A2);
3549     typedef boost::function<Mptr> M;
3550
3551     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3552         return boost::bind(method, instance, _1, _2);
3553     }
3554
3555     static const bool asynchronous = DBusResult2<A1, A2>::asynchronous;
3556
3557     static DBusMessage *methodFunction(DBusConnection *conn,
3558                                        DBusMessage *msg, void *data)
3559     {
3560         try {
3561             typename dbus_traits<A1>::host_type a1;
3562             typename dbus_traits<A2>::host_type a2;
3563
3564             DBusMessageIter iter;
3565             dbus_message_iter_init(msg, &iter);
3566             dbus_traits<A1>::get(conn, msg, iter, a1);
3567             dbus_traits<A2>::get(conn, msg, iter, a2);
3568
3569             (*static_cast<M *>(data))(a1, a2);
3570
3571             if (asynchronous) {
3572                 return NULL;
3573             }
3574
3575             DBusMessage *reply = dbus_message_new_method_return(msg);
3576             if (!reply)
3577                 return NULL;
3578             dbus_message_iter_init_append(reply, &iter);
3579             dbus_traits<A1>::append(iter, a1);
3580             dbus_traits<A2>::append(iter, a2);
3581             return reply;
3582         } catch (...) {
3583             return handleException(msg);
3584         }
3585     }
3586
3587     static void destroyFunction(void *user_data)
3588     {
3589         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3590         delete static_cast<M *>(entry->method_data);
3591     }
3592
3593     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3594     {
3595         GDBusMethodTable entry;
3596         entry.name = strdup(name);
3597         std::string buffer;
3598         buffer += dbus_traits<A1>::getSignature();
3599         buffer += dbus_traits<A2>::getSignature();
3600         entry.signature = strdup(buffer.c_str());
3601         buffer.clear();
3602         buffer += dbus_traits<A1>::getReply();
3603         buffer += dbus_traits<A2>::getReply();
3604         entry.reply = strdup(buffer.c_str());
3605         entry.function = methodFunction;
3606         entry.destroy = destroyFunction;
3607         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3608                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3609         entry.method_data = new M(m);
3610         return entry;
3611     }
3612 };
3613
3614 /** 1 argument, 1 return value */
3615 template <class R,
3616           class A1>
3617 struct MakeMethodEntry< boost::function<R (A1)> >
3618 {
3619     typedef R (Mptr)(A1);
3620     typedef boost::function<Mptr> M;
3621
3622     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3623         return boost::bind(method, instance, _1);
3624     }
3625
3626     static const bool asynchronous = DBusResult1<A1>::asynchronous;
3627
3628     static DBusMessage *methodFunction(DBusConnection *conn,
3629                                        DBusMessage *msg, void *data)
3630     {
3631         try {
3632             typename dbus_traits<R>::host_type r;
3633             typename dbus_traits<A1>::host_type a1;
3634
3635             DBusMessageIter iter;
3636             dbus_message_iter_init(msg, &iter);
3637             dbus_traits<A1>::get(conn, msg, iter, a1);
3638
3639             r = (*static_cast<M *>(data))(a1);
3640
3641             if (asynchronous) {
3642                 return NULL;
3643             }
3644
3645             DBusMessage *reply = dbus_message_new_method_return(msg);
3646             if (!reply)
3647                 return NULL;
3648             dbus_message_iter_init_append(reply, &iter);
3649             dbus_traits<R>::append_retval(iter, r);
3650             dbus_traits<A1>::append(iter, a1);
3651             return reply;
3652         } catch (...) {
3653             return handleException(msg);
3654         }
3655     }
3656
3657     static void destroyFunction(void *user_data)
3658     {
3659         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3660         delete static_cast<M *>(entry->method_data);
3661     }
3662
3663     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3664     {
3665         GDBusMethodTable entry;
3666         entry.name = strdup(name);
3667         std::string buffer;
3668         buffer += dbus_traits<A1>::getSignature();
3669         entry.signature = strdup(buffer.c_str());
3670         buffer.clear();
3671         buffer += dbus_traits<R>::getReply();
3672         buffer += dbus_traits<A1>::getReply();
3673         entry.reply = strdup(buffer.c_str());
3674         entry.function = methodFunction;
3675         entry.destroy = destroyFunction;
3676         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3677                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3678         entry.method_data = new M(m);
3679         return entry;
3680     }
3681 };
3682
3683 /** ===> 1 parameter */
3684 template <class A1>
3685 struct MakeMethodEntry< boost::function<void (A1)> >
3686 {
3687     typedef void (Mptr)(A1);
3688     typedef boost::function<void (A1)> M;
3689
3690     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3691         return boost::bind(method, instance, _1);
3692     }
3693
3694     static const bool asynchronous = DBusResult1<A1>::asynchronous;
3695
3696     static DBusMessage *methodFunction(DBusConnection *conn,
3697                                        DBusMessage *msg, void *data)
3698     {
3699         try {
3700             typename dbus_traits<A1>::host_type a1;
3701
3702             DBusMessageIter iter;
3703             dbus_message_iter_init(msg, &iter);
3704             dbus_traits<A1>::get(conn, msg, iter, a1);
3705
3706             (*static_cast<M *>(data))(a1);
3707
3708             if (asynchronous) {
3709                 return NULL;
3710             }
3711
3712             DBusMessage *reply = dbus_message_new_method_return(msg);
3713             if (!reply)
3714                 return NULL;
3715             dbus_message_iter_init_append(reply, &iter);
3716             dbus_traits<A1>::append(iter, a1);
3717             return reply;
3718         } catch (...) {
3719             return handleException(msg);
3720         }
3721     }
3722
3723     static void destroyFunction(void *user_data)
3724     {
3725         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3726         delete static_cast<M *>(entry->method_data);
3727     }
3728
3729     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3730     {
3731         GDBusMethodTable entry;
3732         entry.name = strdup(name);
3733         std::string buffer;
3734         buffer += dbus_traits<A1>::getSignature();
3735         entry.signature = strdup(buffer.c_str());
3736         buffer.clear();
3737         buffer += dbus_traits<A1>::getReply();
3738         entry.reply = strdup(buffer.c_str());
3739         entry.function = methodFunction;
3740         entry.destroy = destroyFunction;
3741         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA |
3742                                        (asynchronous ? G_DBUS_METHOD_FLAG_ASYNC : 0));
3743         entry.method_data = new M(m);
3744         return entry;
3745     }
3746 };
3747
3748 /** 0 arguments, 1 return value */
3749 template <class R>
3750 struct MakeMethodEntry< boost::function<R ()> >
3751 {
3752     typedef R (Mptr)();
3753     typedef boost::function<Mptr> M;
3754
3755     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3756         return boost::bind(method, instance);
3757     }
3758
3759     static DBusMessage *methodFunction(DBusConnection *conn,
3760                                        DBusMessage *msg, void *data)
3761     {
3762         try {
3763             typename dbus_traits<R>::host_type r;
3764
3765             r = (*static_cast<M *>(data))();
3766
3767             DBusMessage *reply = dbus_message_new_method_return(msg);
3768             if (!reply)
3769                 return NULL;
3770             DBusMessageIter iter;
3771             dbus_message_iter_init_append(reply, &iter);
3772             dbus_traits<R>::append_retval(iter, r);
3773             return reply;
3774         } catch (...) {
3775             return handleException(msg);
3776         }
3777     }
3778     static void destroyFunction(void *user_data)
3779     {
3780         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3781         delete static_cast<M *>(entry->method_data);
3782     }
3783
3784     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3785     {
3786         GDBusMethodTable entry;
3787         entry.name = strdup(name);
3788         std::string buffer;
3789         entry.signature = strdup(buffer.c_str());
3790         buffer.clear();
3791         buffer += dbus_traits<R>::getReply();
3792         entry.reply = strdup(buffer.c_str());
3793         entry.function = methodFunction;
3794         entry.destroy = destroyFunction;
3795         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA);
3796         entry.method_data = new M(m);
3797         return entry;
3798     }
3799 };
3800
3801 /** ===> 0 parameter */
3802 template <>
3803 struct MakeMethodEntry< boost::function<void ()> >
3804 {
3805     typedef void (Mptr)();
3806     typedef boost::function<Mptr> M;
3807
3808     template <class I, class C> static M boostptr(Mptr C::*method, I instance) {
3809         return boost::bind(method, instance);
3810     }
3811
3812     static DBusMessage *methodFunction(DBusConnection *conn,
3813                                        DBusMessage *msg, void *data)
3814     {
3815         try {
3816             (*static_cast<M *>(data))();
3817
3818             DBusMessage *reply = dbus_message_new_method_return(msg);
3819             if (!reply)
3820                 return NULL;
3821             return reply;
3822         } catch (...) {
3823             return handleException(msg);
3824         }
3825     }
3826
3827     static void destroyFunction(void *user_data)
3828     {
3829         GDBusMethodTable *entry = static_cast<GDBusMethodTable *>(user_data);
3830         delete static_cast<M *>(entry->method_data);
3831     }
3832
3833     static GDBusMethodTable make(const char *name, GDBusMethodFlags flags, const M &m)
3834     {
3835         GDBusMethodTable entry;
3836         entry.name = strdup(name);
3837         std::string buffer;
3838         entry.signature = strdup(buffer.c_str());
3839         buffer.clear();
3840         entry.reply = strdup(buffer.c_str());
3841         entry.function = methodFunction;
3842         entry.destroy = destroyFunction;
3843         entry.flags = GDBusMethodFlags(flags | G_DBUS_METHOD_FLAG_METHOD_DATA);
3844         entry.method_data = new M(m);
3845         return entry;
3846     }
3847 };
3848
3849 #endif // INCL_GDBUS_CXX_BRIDGE