>From e95a3e6cc5c8716aae84ff40439000fcf733b6e2 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Mon, 12 Oct 2009 20:51:28 +0200
Subject: [PATCH 09/12] gdbus: per-method callback data

The traditional usage of method callbacks is that all callbacks
share the same global data pointer. When composing a D-Bus object
from several independent modules this may be too limited, for
example when using C++.

This patch introduces G_DBUS_METHOD_FLAG_METHOD_DATA and new
fields at the end of GDBusMethodTable. Old code works as before.
New code which sets the flag is passed the new "method_data"
value as its "user_data" pointer.

This implies that the GDBusMethodTable has to be built up dynamically.
It is still owned and managed by the caller of libgdbus. To
simplify this, a new "destroy" callback can be stored inside the
GDBusMethodTable.
---
 src/gdbus.h  |   12 ++++++++++++
 src/object.c |    6 +++++-
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/src/gdbus.h b/src/gdbus.h
index b1797a0..8149637 100644
--- a/src/gdbus.h
+++ b/src/gdbus.h
@@ -112,6 +112,10 @@ typedef dbus_bool_t (* GDBusPropertySetFunction) (DBusConnection *connection,
  * @G_DBUS_METHOD_FLAG_DEPRECATED: annotate deprecated methods
  * @G_DBUS_METHOD_FLAG_NOREPLY: annotate methods with no reply
  * @G_DBUS_METHOD_FLAG_ASYNC: annotate asynchronous methods
+ * @G_DBUS_METHOD_FLAG_METHOD_DATA: the method is passed the
+ *                                  GDBusMethodTable method_data pointer
+ *                                  instead of the g_dbus_register_interface()
+ *                                  user_data pointer
  *
  * Method flags
  */
@@ -120,6 +124,7 @@ typedef enum {
 	G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
 	G_DBUS_METHOD_FLAG_NOREPLY    = (1 << 1),
 	G_DBUS_METHOD_FLAG_ASYNC      = (1 << 2),
+	G_DBUS_METHOD_FLAG_METHOD_DATA = (1 << 3),
 } GDBusMethodFlags;
 
 /**
@@ -151,6 +156,11 @@ typedef enum {
  * @reply: reply signature
  * @function: method function
  * @flags: method flags
+ * @method_data: passed as GDBusMethodFunction user_data if
+ *               G_DBUS_METHOD_FLAG_METHOD_DATA is set
+ * @destroy: destructor function for method table; not called
+ *           by gdbus itself, because it never frees GDBusMethodTable
+ *           entries, but useful in upper layers
  *
  * Method table
  */
@@ -160,6 +170,8 @@ typedef struct {
 	const char *reply;
 	GDBusMethodFunction function;
 	GDBusMethodFlags flags;
+	void *method_data;
+	GDBusDestroyFunction destroy;
 } GDBusMethodTable;
 
 /**
diff --git a/src/object.c b/src/object.c
index 448fef7..f35ac31 100644
--- a/src/object.c
+++ b/src/object.c
@@ -615,7 +615,11 @@ static DBusHandlerResult handle_message(DBusConnection *connection,
 			continue;
 
 		reply = method->function(connection,
-						message, interface->user_data);
+						message,
+						(method->flags & 
+						 G_DBUS_METHOD_FLAG_METHOD_DATA) ?
+						method->method_data :
+						interface->user_data);
 
 		if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
 			if (reply != NULL)
-- 
1.6.5

