[glib/gdbus-merge] Add an example of exporting a GObject



commit 9a065edf6f51be2ad189cfb02ddd2c806b656303
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 13 00:39:26 2010 -0400

    Add an example of exporting a GObject
    
    This is more manual work than dbus-glib.

 gio/gdbusconnection.c            |    2 +
 gio/tests/Makefile.am            |    4 +
 gio/tests/gdbus-example-export.c |  331 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 337 insertions(+), 0 deletions(-)
---
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index 3c26090..559df84 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -156,6 +156,8 @@
  * <example id="gdbus-subtree-server"><title>D-Bus subtree example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; parse="text" href="../../../../gio/tests/gdbus-example-subtree.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
  *
  * <example id="gdbus-unix-fd-client"><title>D-Bus UNIX File Descriptor example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; parse="text" href="../../../../gio/tests/gdbus-example-unix-fd-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
+ *
+ * <example id="gdbus-export"><title>Exporting a GObject</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; parse="text" href="../../../../gio/tests/gdbus-example-export.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
  */
 
 /* ---------------------------------------------------------------------------------------------------- */
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am
index cbd63a1..f383580 100644
--- a/gio/tests/Makefile.am
+++ b/gio/tests/Makefile.am
@@ -58,6 +58,7 @@ SAMPLE_PROGS = 				\
 	httpd				\
 	send-data			\
 	filter-cat			\
+	gdbus-example-export		\
 	gdbus-example-own-name		\
 	gdbus-example-watch-name	\
 	gdbus-example-watch-proxy	\
@@ -234,6 +235,9 @@ gdbus_example_peer_LDADD   = $(progs_ldadd)
 gdbus_example_proxy_subclass_SOURCES = gdbus-example-proxy-subclass.c
 gdbus_example_proxy_subclass_LDADD   = $(progs_ldadd)
 
+gdbus_example_export_SOURCES = gdbus-example-export.c
+gdbus_example_export_LDADD   = $(progs_ldadd)
+
 EXTRA_DIST += \
 	socket-common.c						\
 	org.gtk.test.gschema					\
diff --git a/gio/tests/gdbus-example-export.c b/gio/tests/gdbus-example-export.c
new file mode 100644
index 0000000..5965ed8
--- /dev/null
+++ b/gio/tests/gdbus-example-export.c
@@ -0,0 +1,331 @@
+#include <gio/gio.h>
+#include <stdlib.h>
+
+* ---------------------------------------------------------------------------------------------------- */
+
+/* The object we want to export */
+typedef struct _MyObjectClass MyObjectClass;
+typedef struct _MyObject MyObject;
+
+struct _MyObjectClass
+{
+  GObjectClass parent_class;
+};
+
+struct _MyObject
+{
+  GObject parent_instance;
+
+  gint count;
+  gchar *name;
+};
+
+enum
+{
+  PROP_0,
+  PROP_COUNT,
+  PROP_NAME
+};
+
+G_DEFINE_TYPE (MyObject, my_object, G_TYPE_OBJECT);
+
+static void
+my_object_finalize (GObject *object)
+{
+  MyObject *myobj = (MyObject*)object;
+
+  g_free (myobj->name);
+
+  G_OBJECT_CLASS (my_object_parent_class)->finalize (object);
+}
+
+static void
+my_object_init (MyObject *object)
+{
+  object->count = 0;
+  object->name = NULL;
+}
+
+static void
+my_object_get_property (GObject    *object,
+                        guint       prop_id,
+                        GValue     *value,
+                        GParamSpec *pspec)
+{
+  MyObject *myobj = (MyObject*)object;
+
+  switch (prop_id)
+    {
+    case PROP_COUNT:
+      g_value_set_int (value, myobj->count);
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, myobj->name);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+my_object_set_property (GObject      *object,
+                        guint         prop_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
+{
+  MyObject *myobj = (MyObject*)object;
+
+  switch (prop_id)
+    {
+    case PROP_COUNT:
+      myobj->count = g_value_get_int (value);
+      break;
+
+    case PROP_NAME:
+      g_free (myobj->name);
+      myobj->name = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+my_object_class_init (MyObjectClass *class)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+  gobject_class->finalize = my_object_finalize;
+  gobject_class->set_property = my_object_set_property;
+  gobject_class->get_property = my_object_get_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_COUNT,
+                                   g_param_spec_int ("count",
+                                                     "Count",
+                                                     "Count",
+                                                     0, 99999, 0,
+                                                     G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_NAME,
+                                   g_param_spec_string ("name",
+                                                        "Name",
+                                                        "Name",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+}
+
+/* A method that we want to export */
+void
+my_object_change_count (MyObject *myobj,
+                        gint      change)
+{
+  myobj->count = 2 * myobj->count + change;
+
+  g_object_notify (G_OBJECT (myobj), "count");
+}
+
+static GDBusNodeInfo *introspection_data = NULL;
+
+/* Introspection data for the service we are exporting */
+static const gchar introspection_xml[] =
+  "<node>"
+  "  <interface name='org.myorg.MyObject'>"
+  "    <method name='ChangeCount'>"
+  "      <arg type='i' name='change' direction='in'/>"
+  "    </method>"
+  "    <property type='i' name='Count' access='read'/>"
+  "    <property type='s' name='Name' access='readwrite'/>"
+  "  </interface>"
+  "</node>";
+
+
+static void
+handle_method_call (GDBusConnection       *connection,
+                    const gchar           *sender,
+                    const gchar           *object_path,
+                    const gchar           *interface_name,
+                    const gchar           *method_name,
+                    GVariant              *parameters,
+                    GDBusMethodInvocation *invocation,
+                    gpointer               user_data)
+{
+  MyObject *myobj = user_data;
+
+  if (g_strcmp0 (method_name, "ChangeCount") == 0)
+    {
+      gint change;
+      g_variant_get (parameters, "(i)", &change);
+
+      my_object_change_count (myobj, change);
+
+      g_dbus_method_invocation_return_value (invocation, NULL);
+    }
+}
+
+static GVariant *
+handle_get_property (GDBusConnection  *connection,
+                     const gchar      *sender,
+                     const gchar      *object_path,
+                     const gchar      *interface_name,
+                     const gchar      *property_name,
+                     GError          **error,
+                     gpointer          user_data)
+{
+  GVariant *ret;
+  MyObject *myobj = user_data;
+
+  ret = NULL;
+  if (g_strcmp0 (property_name, "Count") == 0)
+    {
+      ret = g_variant_new_int32 (myobj->count);
+    }
+  else if (g_strcmp0 (property_name, "Name") == 0)
+    {
+      ret = g_variant_new_string (myobj->name ? myobj->name : "");
+    }
+
+  return ret;
+}
+
+static gboolean
+handle_set_property (GDBusConnection  *connection,
+                     const gchar      *sender,
+                     const gchar      *object_path,
+                     const gchar      *interface_name,
+                     const gchar      *property_name,
+                     GVariant         *value,
+                     GError          **error,
+                     gpointer          user_data)
+{
+  MyObject *myobj = user_data;
+
+  if (g_strcmp0 (property_name, "Count") == 0)
+    {
+      g_object_set (myobj, "count", g_variant_get_int32 (value), NULL);
+    }
+  else if (g_strcmp0 (property_name, "Name") == 0)
+    {
+      g_object_set (myobj, "name", g_variant_get_string (value, NULL), NULL);
+    }
+
+  return TRUE;
+}
+
+
+/* for now */
+static const GDBusInterfaceVTable interface_vtable =
+{
+  handle_method_call,
+  handle_get_property,
+  handle_set_property
+};
+
+static void
+send_property_change (GObject         *obj,
+                      GParamSpec      *pspec,
+                      GDBusConnection *connection)
+{
+  GVariantBuilder *builder;
+  MyObject *myobj = (MyObject *)obj;
+
+  builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+
+  if (g_strcmp0 (pspec->name, "count") == 0)
+    g_variant_builder_add (builder,
+                           "{sv}",
+                           "Count", g_variant_new_int32 (myobj->count));
+  else if (g_strcmp0 (pspec->name, "name") == 0)
+    g_variant_builder_add (builder,
+                           "{sv}",
+                           "Name", g_variant_new_string (myobj->name ? myobj->name : ""));
+
+  g_dbus_connection_emit_signal (connection,
+                                 NULL,
+                                 "/org/myorg/MyObject",
+                                 "org.myorg.MyObject",
+                                 "PropertiesChanged",
+                                 g_variant_new ("(sa{sv})",
+                                                "org.myorg.MyObject",
+                                                builder),
+                                 NULL);
+}
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+                 const gchar     *name,
+                 gpointer         user_data)
+{
+  MyObject *myobj = user_data;
+  guint registration_id;
+
+  g_signal_connect (myobj, "notify",
+                    G_CALLBACK (send_property_change), connection);
+  registration_id = g_dbus_connection_register_object (connection,
+                                                       "/org/myorg/MyObject",
+                                                       "org.myorg.MyObject",
+                                                       introspection_data->interfaces[0],
+                                                       &interface_vtable,
+                                                       myobj,
+                                                       NULL,  /* user_data_free_func */
+                                                       NULL); /* GError** */
+  g_assert (registration_id > 0);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+  exit (1);
+}
+
+int
+main (int argc, char *argv[])
+{
+  guint owner_id;
+  GMainLoop *loop;
+  MyObject *myobj;
+
+  g_type_init ();
+
+  /* We are lazy here - we don't want to manually provide
+   * the introspection data structures - so we just build
+   * them from XML.
+   */
+  introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+  g_assert (introspection_data != NULL);
+
+  myobj = g_object_new (my_object_get_type (), NULL);
+
+  owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+                             "org.myorg.MyObject",
+                             G_BUS_NAME_OWNER_FLAGS_NONE,
+                             on_bus_acquired,
+                             on_name_acquired,
+                             on_name_lost,
+                             myobj,
+                             NULL);
+
+  loop = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (loop);
+
+  g_bus_unown_name (owner_id);
+
+  g_dbus_node_info_unref (introspection_data);
+
+  g_object_unref (myobj);
+
+  return 0;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]