[glib/gdbus-merge] Add an example of exporting a GObject
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/gdbus-merge] Add an example of exporting a GObject
- Date: Thu, 13 May 2010 04:43:05 +0000 (UTC)
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]