]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
2005-06-17 Colin Walters <walters@verbum.org>
authorColin Walters <walters@verbum.org>
Fri, 17 Jun 2005 14:29:48 +0000 (14:29 +0000)
committerColin Walters <walters@verbum.org>
Fri, 17 Jun 2005 14:29:48 +0000 (14:29 +0000)
* glib/dbus-gproxy.c (dbus_g_proxy_emit_remote_signal): Don't
spew warnings if we get malformed remote signals.

* glib/dbus-gobject.c (propsig_iterate): New function.
(lookup_object_info): New function, extracted from
lookup_object_and_method.
(introspect_properties, introspect_signals): Delete; these
are merged into write_interface.
(write_interface): Write out signals and properties here;
dump the org.gtk.object stuff and use the interface given
in the introspection data blob.  Also fix up property XML.
(lookup_values): New function.
(introspect_interfaces): Gather a mapping from interface to a
list of its methods, signals, and properties, then write out
each interface.
(lookup_object_and_method): Use lookup_object_info.
(struct DBusGSignalClosure): Add interface.
(dbus_g_signal_closure_new): Add interface. Don't dup signame;
we can just use the constant data.
(dbus_g_signal_closure_finalize): Don't free signal name.
(signal_emitter_marshaller): Use interface from signal closure.
(export_signals): Only export signals mentioned in introspection
blob.
(dbus_g_connection_register_g_object): Warn if we have no
introspection data for an object.
(funcsig_equal): Remove unused variable.
(dbus_g_object_register_marshaller): Take varargs instead of
list.
(dbus_g_object_register_marshaller_array): New function,
extracted from old dbus_g_object_register_marshaller.

* glib/dbus-binding-tool-glib.c (struct DBusBindingToolCData): Add
signals and property data.
(write_quoted_string): New function, extracted from generate_glue.
(generate_glue): Write signals and properties to introspection
blob.

* dbus/dbus-glib.h (struct DBusGObjectInfo): Include
exported_signals and exported_properties.
(dbus_g_object_register_marshaller): Update prototype.
(dbus_g_object_register_marshaller_array): Prototype.

* test/glib/test-dbus-glib.c: Extend testing to cover new signals.

* test/glib/test-service-glib.c: Add new test signals and method
to emit them.

* test/glib/test-service-glib.xml: Add some test signals.

* test/glib/Makefile.am (BUILT_SOURCES): Add my-object-marshal.c
and my-object-marshal.h
(test_service_glib_SOURCES, test_dbus_glib_SOURCES): Add
my-object-marshal.c.
(my-object-marshal.c, my-object-marshal.h): Implement.

* test/glib/.cvsignore: Update.

* doc/TODO: Remove two GLib TODO items fixed by this
patch.

12 files changed:
ChangeLog
dbus/dbus-glib.h
doc/TODO
glib/dbus-binding-tool-glib.c
glib/dbus-gobject.c
glib/dbus-gproxy.c
test/glib/.cvsignore
test/glib/Makefile.am
test/glib/my-object-marshal.list [new file with mode: 0644]
test/glib/test-dbus-glib.c
test/glib/test-service-glib.c
test/glib/test-service-glib.xml

index 2f6b058c4103d6707e122f1e14f3371826b05f59..8b4f8796330b0162f454ec2b6106c6c97a5690d0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,65 @@
+2005-06-17  Colin Walters  <walters@verbum.org>
+
+       * glib/dbus-gproxy.c (dbus_g_proxy_emit_remote_signal): Don't
+       spew warnings if we get malformed remote signals.
+
+       * glib/dbus-gobject.c (propsig_iterate): New function.
+       (lookup_object_info): New function, extracted from
+       lookup_object_and_method.
+       (introspect_properties, introspect_signals): Delete; these
+       are merged into write_interface.
+       (write_interface): Write out signals and properties here;
+       dump the org.gtk.object stuff and use the interface given
+       in the introspection data blob.  Also fix up property XML.
+       (lookup_values): New function.
+       (introspect_interfaces): Gather a mapping from interface to a
+       list of its methods, signals, and properties, then write out
+       each interface.
+       (lookup_object_and_method): Use lookup_object_info.
+       (struct DBusGSignalClosure): Add interface.
+       (dbus_g_signal_closure_new): Add interface. Don't dup signame;
+       we can just use the constant data.
+       (dbus_g_signal_closure_finalize): Don't free signal name.
+       (signal_emitter_marshaller): Use interface from signal closure.
+       (export_signals): Only export signals mentioned in introspection
+       blob.
+       (dbus_g_connection_register_g_object): Warn if we have no
+       introspection data for an object.
+       (funcsig_equal): Remove unused variable.
+       (dbus_g_object_register_marshaller): Take varargs instead of
+       list.
+       (dbus_g_object_register_marshaller_array): New function,
+       extracted from old dbus_g_object_register_marshaller.
+
+       * glib/dbus-binding-tool-glib.c (struct DBusBindingToolCData): Add
+       signals and property data.
+       (write_quoted_string): New function, extracted from generate_glue.
+       (generate_glue): Write signals and properties to introspection
+       blob.
+
+       * dbus/dbus-glib.h (struct DBusGObjectInfo): Include
+       exported_signals and exported_properties.
+       (dbus_g_object_register_marshaller): Update prototype.
+       (dbus_g_object_register_marshaller_array): Prototype.
+       
+       * test/glib/test-dbus-glib.c: Extend testing to cover new signals.
+
+       * test/glib/test-service-glib.c: Add new test signals and method
+       to emit them.
+
+       * test/glib/test-service-glib.xml: Add some test signals.
+
+       * test/glib/Makefile.am (BUILT_SOURCES): Add my-object-marshal.c
+       and my-object-marshal.h
+       (test_service_glib_SOURCES, test_dbus_glib_SOURCES): Add
+       my-object-marshal.c.
+       (my-object-marshal.c, my-object-marshal.h): Implement.
+
+       * test/glib/.cvsignore: Update.
+
+       * doc/TODO: Remove two GLib TODO items fixed by this
+       patch.
+
 2005-06-16  Colin Walters  <walters@verbum.org>
 
        * doc/TODO: Update for GLib bindings.
index 80ed7f4f2c84b8ff56e722b3ff0beb184ce570ea..4debe6fe8d93a27f42daea5efef334fa1666db4e 100644 (file)
@@ -109,9 +109,11 @@ struct DBusGObjectInfo
   int   format_version;         /**< Allows us to change the rest of this struct
                                  *   by adding DBusGObjectInfo2, DBusGObjectInfo3, etc.
                                  */
-  const DBusGMethodInfo *infos; /**< Array of method pointers */
-  int   n_infos;                /**< Length of the infos array */
+  const DBusGMethodInfo *method_infos; /**< Array of method pointers */
+  int   n_method_infos;                /**< Length of the infos array */
   const char *data;             /**< Introspection data */
+  const char *exported_signals;  /**< Exported signals */
+  const char *exported_properties;  /**< Exported properties */
 };
 
 void dbus_g_object_type_install_info     (GType                 object_type,
@@ -189,13 +191,16 @@ gboolean     dbus_g_value_iterator_get_values       (DBusGValueIterator   *iter,
 void         dbus_g_value_iterator_recurse          (DBusGValueIterator   *iter,
                                                     DBusGValueIterator   *sub);
 
-void         dbus_g_value_free              (DBusGValue          *value);
+void         dbus_g_value_free                      (DBusGValue          *value);
 
 
-void         dbus_g_object_register_marshaller  (GType             rettype,
-                                                guint             n_types,
-                                                const GType      *param_types,
-                                                GClosureMarshal   marshaller);
+void         dbus_g_object_register_marshaller      (GClosureMarshal  marshaller,
+                                                    GType            rettype,
+                                                    ...);
+void         dbus_g_object_register_marshaller_array(GClosureMarshal  marshaller,
+                                                    GType            rettype,
+                                                    guint            n_types,
+                                                    const GType*     types);
 
 typedef struct DBusGProxy       DBusGProxy;
 typedef struct DBusGProxyClass  DBusGProxyClass;
index 3c0e6cb3b91085a5ac7f6247b05e4ccf74e0039c..4b953baddd3500c96a03917b9b7b511740be8644 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -30,11 +30,6 @@ Important for 1.0 GLib Bindings
 
  - Annotations for "do not take ownership of this return value" on server
 
- - Fix/test signals
-
- - Don't autoexport signals and properties; use metadata either in
-   code (preferable) or annotation in XML
-
  - Fix TYPE_OBJECT_PATH marshalling; see:
    http://lists.freedesktop.org/archives/dbus/2005-June/002774.html
 
index b04386bc02a64626fe1084195a41f72ddffaaa74..fd849a86d030c61932856678e503e29d8c04ccd3 100644 (file)
@@ -48,6 +48,8 @@ typedef struct
   
   GHashTable *generated;
   GString *blob;
+  GString *signal_blob;
+  GString *property_blob;
   guint count;
 } DBusBindingToolCData;
 
@@ -364,6 +366,31 @@ write_printf_to_iochannel (const char *fmt, GIOChannel *channel, GError **error,
   return ret;
 }
 
+static gboolean
+write_quoted_string (GIOChannel *channel, GString *string, GError **error)
+{
+  guint i;
+
+  WRITE_OR_LOSE ("\"");
+  for (i = 0; i < string->len; i++)
+    {
+      if (string->str[i] != '\0')
+       {
+         if (!g_io_channel_write_chars (channel, string->str + i, 1, NULL, error))
+           return FALSE;
+       }
+      else
+       {
+         if (!g_io_channel_write_chars (channel, "\\0", -1, NULL, error))
+           return FALSE;
+       }
+    }
+  WRITE_OR_LOSE ("\\0\"");
+  return TRUE;
+ io_lose:
+  return FALSE;
+}
+
 static gboolean
 generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
 {
@@ -371,7 +398,6 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
     {
       GString *object_introspection_data_blob;
       GIOChannel *channel;
-      guint i;
 
       channel = data->channel;
       
@@ -380,6 +406,9 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
       data->blob = object_introspection_data_blob;
       data->count = 0;
 
+      data->signal_blob = g_string_new_len ("", 0);
+      data->property_blob = g_string_new_len ("", 0);
+
       if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, data->prefix))
        goto io_lose;
 
@@ -402,29 +431,28 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
        goto io_lose;
       if (!write_printf_to_iochannel ("  %d,\n", channel, error, data->count))
        goto io_lose;
-      WRITE_OR_LOSE("  \"");
-      for (i = 0; i < object_introspection_data_blob->len; i++)
-       {
-         if (object_introspection_data_blob->str[i] != '\0')
-           {
-             if (!g_io_channel_write_chars (channel, object_introspection_data_blob->str + i, 1, NULL, error))
-               return FALSE;
-           }
-         else
-           {
-             if (!g_io_channel_write_chars (channel, "\\0", -1, NULL, error))
-               return FALSE;
-           }
-       }
-      WRITE_OR_LOSE ("\"\n};\n\n");
+
+      if (!write_quoted_string (channel, object_introspection_data_blob, error))
+       goto io_lose;
+      WRITE_OR_LOSE (",\n");
+      if (!write_quoted_string (channel, data->signal_blob, error))
+       goto io_lose;
+      WRITE_OR_LOSE (",\n");
+      if (!write_quoted_string (channel, data->property_blob, error))
+       goto io_lose;
+      WRITE_OR_LOSE ("\n};\n\n");
 
       g_string_free (object_introspection_data_blob, TRUE);
+      g_string_free (data->signal_blob, TRUE);
+      g_string_free (data->property_blob, TRUE);
     }
   else
     {
       GIOChannel *channel;
       InterfaceInfo *interface;
       GSList *methods;
+      GSList *signals;
+      GSList *properties;
       GSList *tmp;
       const char *interface_c_name;
       GString *object_introspection_data_blob;
@@ -532,6 +560,34 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
 
           data->count++;
         }
+
+      signals = interface_info_get_signals (interface);
+
+      for (tmp = signals; tmp != NULL; tmp = g_slist_next (tmp))
+        {
+          SignalInfo *sig;
+         
+         sig = tmp->data;
+
+         g_string_append (data->signal_blob, interface_info_get_name (interface));
+         g_string_append_c (data->signal_blob, '\0');
+         g_string_append (data->signal_blob, signal_info_get_name (sig));
+         g_string_append_c (data->signal_blob, '\0');
+       }
+
+      properties = interface_info_get_properties (interface);
+
+      for (tmp = properties; tmp != NULL; tmp = g_slist_next (tmp))
+        {
+          PropertyInfo *prop;
+         
+         prop = tmp->data;
+
+         g_string_append (data->property_blob, interface_info_get_name (interface));
+         g_string_append_c (data->property_blob, '\0');
+         g_string_append (data->property_blob, property_info_get_name (prop));
+         g_string_append_c (data->property_blob, '\0');
+       }
     }
   return TRUE;
  io_lose:
index 7a57d4ea6fbc16fef1abc625478bc56b0860194b..40d1da03f6564c9c9ef0b3f2cf2297094f204b1d 100644 (file)
@@ -204,160 +204,94 @@ method_output_signature_from_object_info (const DBusGObjectInfo *object,
   return method_dir_signature_from_object_info (object, method, FALSE);
 }
 
-static void
-gobject_unregister_function (DBusConnection  *connection,
-                             void            *user_data)
+static const char *
+propsig_iterate (const char *data, const char **iface, const char **name)
 {
-  GObject *object;
-
-  object = G_OBJECT (user_data);
+  *iface = data;
 
-  /* FIXME */
+  data = string_table_next (data);
+  *name = data;
 
+  return string_table_next (data);
 }
 
-static void
-introspect_properties (GObject *object, GString *xml)
+static const DBusGObjectInfo *
+lookup_object_info (GObject *object)
 {
-  unsigned int i;
-  unsigned int n_specs;
-  GType last_type;
-  GParamSpec **specs;
+  const DBusGObjectInfo *ret;
+  GType classtype;
+  
+  ret = NULL;
+  
+  g_static_rw_lock_reader_lock (&globals_lock);
 
-  last_type = G_TYPE_INVALID;
-  specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object),
-                                          &n_specs);
+  if (info_hash == NULL)
+    goto out;
 
-  for (i = 0; i < n_specs; i++ )
+  for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
     {
-      char *s;
-      const char *dbus_type;
-      gboolean can_set;
-      gboolean can_get;
-      GParamSpec *spec = specs[i];
-      
-      dbus_type = dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
-      if (dbus_type == NULL)
-       continue;
-      
-      if (spec->owner_type != last_type)
-       {
-          if (last_type != G_TYPE_INVALID)
-            g_string_append (xml, "  </interface>\n");
-
+      const DBusGObjectInfo *info;
 
-          /* FIXME what should the namespace on the interface be in
-           * general?  should people be able to set it for their
-           * objects?
-           */
-          g_string_append (xml, "  <interface name=\"org.gtk.objects.");
-          g_string_append (xml, g_type_name (spec->owner_type));
-          g_string_append (xml, "\">\n");
+      info = g_hash_table_lookup (info_hash, g_type_class_peek (classtype));
 
-          last_type = spec->owner_type;
+      if (info != NULL && info->format_version == 0)
+       {
+         ret = info;
+         break;
        }
-
-      can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
-                (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
-      
-      can_get = (spec->flags & G_PARAM_READABLE) != 0;
-
-      s = uscore_to_wincaps (spec->name);
-      
-      if (can_set || can_get)
-        {
-          g_string_append (xml, "    <property name=\"");
-          g_string_append (xml, s);
-          g_string_append (xml, "\" type=\"");
-          g_string_append (xml, dbus_type);
-          g_string_append (xml, "\" access=\"");
-
-          if (can_set && can_get)
-            g_string_append (xml, "readwrite");
-          else if (can_get)
-            g_string_append (xml, "read");
-          else
-            {
-              g_assert (can_set);
-              g_string_append (xml, "write");
-            }
-          
-          g_string_append (xml, "\"/>\n");
-        }
-      
-      g_free (s);
     }
 
-  if (last_type != G_TYPE_INVALID)
-    g_string_append (xml, "  </interface>\n");
+ out:
+  g_static_rw_lock_reader_unlock (&globals_lock);
 
-  g_free (specs);
+  return ret;
 }
 
 static void
-introspect_signals (GType type, GString *xml)
+gobject_unregister_function (DBusConnection  *connection,
+                             void            *user_data)
 {
-  guint i;
-  guint *ids, n_ids;
-
-  ids = g_signal_list_ids (type, &n_ids);
-  if (!n_ids)
-    return;
-
-  g_string_append (xml, "  <interface name=\"org.gtk.objects.");
-  g_string_append (xml, g_type_name (type));
-  g_string_append (xml, "\">\n");
-
-  /* FIXME: recurse to parent types ? */
-  for (i = 0; i < n_ids; i++)
-    {
-      guint arg;
-      GSignalQuery query;
-      
-      g_signal_query (ids[i], &query);
-
-      if (query.return_type != G_TYPE_NONE)
-       continue; /* FIXME: these could be listed as methods ? */
-
-      g_string_append (xml, "    <signal name=\"");
-      g_string_append (xml, query.signal_name);
-      g_string_append (xml, "\">\n");
-
-      for (arg = 0; arg < query.n_params; arg++)
-       {
-         const char *dbus_type = dbus_gtype_to_signature (query.param_types[arg]);
+  GObject *object;
 
-         if (!dbus_type)
-           continue;
-         
-          g_string_append (xml, "      <arg type=\"");
-          g_string_append (xml, dbus_type);
-          g_string_append (xml, "\"/>\n");
-       }
+  object = G_OBJECT (user_data);
 
-      g_string_append (xml, "    </signal>\n");
-    }
+  /* FIXME */
 
-  g_string_append (xml, "  </interface>\n");
 }
 
 typedef struct
 {
   GString *xml;
+  GType gtype;
   const DBusGObjectInfo *object_info;
-} DBusGlibWriteIterfaceData;
+} DBusGLibWriteIterfaceData;
+
+typedef struct
+{
+  GSList *methods;
+  GSList *signals;
+  GSList *properties;
+} DBusGLibWriteInterfaceValues;
 
 static void
 write_interface (gpointer key, gpointer val, gpointer user_data)
 {
   const char *name;
   GSList *methods;
+  GSList *signals;
+  GSList *properties;
   GString *xml;
   const DBusGObjectInfo *object_info;
-  DBusGlibWriteIterfaceData *data;
+  DBusGLibWriteIterfaceData *data;
+  DBusGLibWriteInterfaceValues *values;
 
   name = key;
-  methods = val;
+
+  values = val;
+  methods = values->methods;
+  signals = values->signals;
+  properties = values->properties;
+
   data = user_data;
   xml = data->xml;
   object_info = data->object_info;
@@ -390,64 +324,177 @@ write_interface (gpointer key, gpointer val, gpointer user_data)
 
        }
       g_string_append (xml, "    </method>\n");
+
+    }
+  g_slist_free (values->methods);
+
+  for (; signals; signals = signals->next)
+    {
+      guint id;
+      guint arg;
+      const char *signame;
+      GSignalQuery query;
+      char *s;
+
+      signame = signals->data;
+
+      s = _dbus_gutils_wincaps_to_uscore (signame);
+      
+      id = g_signal_lookup (s, data->gtype);
+      g_assert (id != 0);
+
+      g_signal_query (id, &query);
+      g_assert (query.return_type == G_TYPE_NONE);
+
+      g_string_append_printf (xml, "    <signal name=\"%s\">\n", signame);
+
+      for (arg = 0; arg < query.n_params; arg++)
+       {
+         const char *dbus_type = dbus_gtype_to_signature (query.param_types[arg]);
+
+         g_assert (dbus_type != NULL);
+
+          g_string_append (xml, "      <arg type=\"");
+          g_string_append (xml, dbus_type);
+          g_string_append (xml, "\"/>\n");
+       }
+
+      g_string_append (xml, "    </signal>\n");
+      g_free (s);
+    }
+  g_slist_free (values->signals);
+
+  for (; properties; properties = properties->next)
+    {
+      const char *propname;
+      GParamSpec *spec;
+      const char *dbus_type;
+      gboolean can_set;
+      gboolean can_get;
+      char *s;
+
+      propname = properties->data;
+
+      s = _dbus_gutils_wincaps_to_uscore (spec->name);
+
+      spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
+      g_assert (spec != NULL);
+      g_free (s);
+      
+      dbus_type = dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
+      g_assert (dbus_type != NULL);
+      
+      can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
+                (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
+      
+      can_get = (spec->flags & G_PARAM_READABLE) != 0;
+      
+      if (can_set || can_get)
+       {
+         g_string_append_printf (xml, "    <property name=\"%s\" ", propname);
+         g_string_append (xml, "type=\"");
+         g_string_append (xml, dbus_type);
+         g_string_append (xml, "\" access=\"");
+
+         if (can_set && can_get)
+           g_string_append (xml, "readwrite");
+         else if (can_get)
+           g_string_append (xml, "read");
+         else
+           {
+             g_assert (can_set);
+             g_string_append (xml, "write");
+           }
+          
+         g_string_append (xml, "\"/>\n");
+       }
+      
+      g_free (s);
+
+      g_string_append (xml, "    </property>\n");
     }
+  g_slist_free (values->properties);
 
+  g_free (values);
   g_string_append (xml, "  </interface>\n");
 }
 
+static DBusGLibWriteInterfaceValues *
+lookup_values (GHashTable *interfaces, const char *method_interface)
+{
+  DBusGLibWriteInterfaceValues *values;
+  if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
+    {
+      values = g_new0 (DBusGLibWriteInterfaceValues, 1);
+      g_hash_table_insert (interfaces, (gpointer) method_interface, values);
+    }
+  return values;
+}
+
 static void
 introspect_interfaces (GObject *object, GString *xml)
 {
-  GType classtype;
+  const DBusGObjectInfo *info;
+  DBusGLibWriteIterfaceData data;
+  int i;
+  GHashTable *interfaces;
+  DBusGLibWriteInterfaceValues *values;
+  const char *propsig;
 
-  g_static_rw_lock_reader_lock (&globals_lock);
+  info = lookup_object_info (object);
 
-  for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
+  g_assert (info != NULL);
+
+  /* Gather a list of all interfaces, indexed into their methods */
+  interfaces = g_hash_table_new (g_str_hash, g_str_equal);
+  for (i = 0; i < info->n_method_infos; i++)
     {
-      const DBusGObjectInfo *info;
-      DBusGlibWriteIterfaceData data;
+      const char *method_name;
+      const char *method_interface;
+      const char *method_args;
+      const DBusGMethodInfo *method;
 
-      info = g_hash_table_lookup (info_hash,
-                                 g_type_class_peek (classtype));
+      method = &(info->method_infos[i]);
 
-      if (info != NULL && info->format_version == 0)
-       {
-         int i;
-         GHashTable *interfaces;
+      method_interface = method_interface_from_object_info (info, method);
+      method_name = method_name_from_object_info (info, method);
+      method_args = method_arg_info_from_object_info (info, method);
 
-         /* Gather a list of all interfaces, indexed into their methods */
-         interfaces = g_hash_table_new (g_str_hash, g_str_equal);
-         for (i = 0; i < info->n_infos; i++)
-           {
-             const char *method_name;
-             const char *method_interface;
-             const char *method_args;
-             const DBusGMethodInfo *method;
-             GSList *methods;
-
-             method = &(info->infos[i]);
-
-             method_interface = method_interface_from_object_info (info, method);
-             method_name = method_name_from_object_info (info, method);
-             method_args = method_arg_info_from_object_info (info, method);
-
-             if ((methods = g_hash_table_lookup (interfaces, method_interface)) == NULL)
-                 methods = g_slist_prepend (NULL, (gpointer) method);
-             else
-                 methods = g_slist_prepend (methods, (gpointer) method);
-             g_hash_table_insert (interfaces, (gpointer) method_interface, methods);
-           }
+      values = lookup_values (interfaces, method_interface);
+      values->methods = g_slist_prepend (values->methods, (gpointer) method);
+    }
 
-         memset (&data, 0, sizeof (data));
-         data.xml = xml;
-         data.object_info = info;
-         g_hash_table_foreach (interfaces, write_interface, &data);
+  propsig = info->exported_signals;
+  while (*propsig)
+    {
+      const char *iface;
+      const char *signame;
 
-         g_hash_table_destroy (interfaces);
-       }
+      propsig = propsig_iterate (propsig, &iface, &signame);
+
+      values = lookup_values (interfaces, iface);
+      values->signals = g_slist_prepend (values->signals, (gpointer) signame);
     }
 
-  g_static_rw_lock_reader_unlock (&globals_lock);
+  propsig = info->exported_properties;
+  while (*propsig)
+    {
+      const char *iface;
+      const char *propname;
+
+      propsig = propsig_iterate (propsig, &iface, &propname);
+
+      values = lookup_values (interfaces, iface);
+      values->properties = g_slist_prepend (values->properties, (gpointer) propname);
+    }
+  
+  memset (&data, 0, sizeof (data));
+  data.xml = xml;
+  data.gtype = G_TYPE_FROM_INSTANCE (object);
+  data.object_info = info;
+  g_hash_table_foreach (interfaces, write_interface, &data);
+  
+  g_hash_table_destroy (interfaces);
 }
 
 static DBusHandlerResult
@@ -492,8 +539,6 @@ handle_introspect (DBusConnection *connection,
   g_string_append (xml, "    </method>\n");
   g_string_append (xml, "  </interface>\n");
   
-  introspect_signals (G_OBJECT_TYPE (object), xml);
-  introspect_properties (object, xml);
   introspect_interfaces (object, xml);
 
   /* Append child nodes */
@@ -605,64 +650,47 @@ lookup_object_and_method (GObject      *object,
                          const DBusGObjectInfo **object_ret,
                          const DBusGMethodInfo **method_ret)
 {
-  GType classtype;
   const char *interface;
   const char *member;
   const char *signature;
   gboolean ret;
+  const DBusGObjectInfo *info;
+  int i;
 
   interface = dbus_message_get_interface (message);
   member = dbus_message_get_member (message);
   signature = dbus_message_get_signature (message);
   ret = FALSE;
 
-  g_static_rw_lock_reader_lock (&globals_lock);
-
-  if (!info_hash)
-    goto out;
+  info = lookup_object_info (object);
+  *object_ret = info;
   
-  for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
+  for (i = 0; i < info->n_method_infos; i++)
     {
-      const DBusGObjectInfo *info;
-
-      info = g_hash_table_lookup (info_hash,
-                                 g_type_class_peek (classtype));
-
-      *object_ret = info;
-
-      if (info != NULL && info->format_version == 0)
+      const char *expected_member;
+      const char *expected_interface;
+      char *expected_signature;
+      const DBusGMethodInfo *method;
+
+      method = &(info->method_infos[i]);
+
+      /* Check method interface/name and input signature */ 
+      expected_interface = method_interface_from_object_info (*object_ret, method);
+      expected_member = method_name_from_object_info (*object_ret, method);
+      expected_signature = method_input_signature_from_object_info (*object_ret, method);
+
+      if ((interface == NULL
+          || strcmp (expected_interface, interface) == 0)
+         && strcmp (expected_member, member) == 0
+         && strcmp (expected_signature, signature) == 0)
        {
-         int i;
-         for (i = 0; i < info->n_infos; i++)
-           {
-             const char *expected_member;
-             const char *expected_interface;
-             char *expected_signature;
-             const DBusGMethodInfo *method;
-
-             method = &(info->infos[i]);
-
-             /* Check method interface/name and input signature */ 
-             expected_interface = method_interface_from_object_info (*object_ret, method);
-             expected_member = method_name_from_object_info (*object_ret, method);
-             expected_signature = method_input_signature_from_object_info (*object_ret, method);
-
-             if ((interface == NULL
-                  || strcmp (expected_interface, interface) == 0)
-                 && strcmp (expected_member, member) == 0
-                 && strcmp (expected_signature, signature) == 0)
-               {
-                 g_free (expected_signature);
-                 *method_ret = method;
-                 ret = TRUE;
-                 goto out;
-               }
-             g_free (expected_signature);
-           }
+         g_free (expected_signature);
+         *method_ret = method;
+         return TRUE;
        }
+      g_free (expected_signature);
     }
- out:
-  g_static_rw_lock_reader_unlock (&globals_lock);
+
   return ret;
 }
 
@@ -1084,13 +1112,15 @@ typedef struct {
   GClosure         closure;
   DBusGConnection *connection;
   GObject         *object;
-  char            *signame;
+  const char      *signame;
+  const char      *sigiface;
 } DBusGSignalClosure;
 
 static GClosure *
 dbus_g_signal_closure_new (DBusGConnection *connection,
                           GObject         *object,
-                          const char      *signame)
+                          const char      *signame,
+                          const char      *sigiface)
 {
   DBusGSignalClosure *closure;
   
@@ -1098,7 +1128,8 @@ dbus_g_signal_closure_new (DBusGConnection *connection,
 
   closure->connection = dbus_g_connection_ref (connection);
   closure->object = object;
-  closure->signame = g_strdup (signame);
+  closure->signame = signame;
+  closure->sigiface = sigiface;
   return (GClosure*) closure;
 }
 
@@ -1109,7 +1140,6 @@ dbus_g_signal_closure_finalize (gpointer data,
   DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
 
   dbus_g_connection_unref (sigclosure->connection);
-  g_free (sigclosure->signame);
 }
 
 static void
@@ -1135,7 +1165,7 @@ signal_emitter_marshaller (GClosure        *closure,
   g_assert (path != NULL);
 
   signal = dbus_message_new_signal (path,
-                                   "org.gtk.objects",
+                                   sigclosure->sigiface,
                                    sigclosure->signame);
   if (!signal)
     {
@@ -1163,34 +1193,52 @@ signal_emitter_marshaller (GClosure        *closure,
 }
 
 static void
-export_signals (DBusGConnection *connection, GObject *object)
+export_signals (DBusGConnection *connection, const DBusGObjectInfo *info, GObject *object)
 {
-  guint i;
-  guint *ids, n_ids;
+  GType gtype;
+  const char *sigdata;
+  const char *iface;
+  const char *signame;
 
-  ids = g_signal_list_ids (G_TYPE_FROM_INSTANCE (object), &n_ids);
-  if (!n_ids)
-    return;
+  gtype = G_TYPE_FROM_INSTANCE (object);
 
-  /* FIXME: recurse to parent types ? */
-  for (i = 0; i < n_ids; i++)
+  sigdata = info->exported_signals;
+  
+  while (*sigdata != '\0')
     {
+      guint id;
       GSignalQuery query;
       GClosure *closure;
+      char *s;
+
+      sigdata = propsig_iterate (sigdata, &iface, &signame);
       
-      g_signal_query (ids[i], &query);
+      s = _dbus_gutils_wincaps_to_uscore (signame);
+
+      id = g_signal_lookup (s, gtype);
+      if (id == 0)
+       {
+         g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
+                    s, signame, g_type_name (gtype));
+         g_free (s);
+         continue;
+       }
+
+      g_signal_query (id, &query);
 
       if (query.return_type != G_TYPE_NONE)
        {
-         g_warning("Not exporting signal '%s' as it has a return type %s", query.signal_name, g_type_name (query.return_type));
+         g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
+                    s, g_type_name (gtype), g_type_name (query.return_type));
+         g_free (s);
          continue; /* FIXME: these could be listed as methods ? */
        }
       
-      closure = dbus_g_signal_closure_new (connection, object, query.signal_name);
+      closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
       g_closure_set_marshal (closure, signal_emitter_marshaller);
 
       g_signal_connect_closure_by_id (object,
-                                     ids[i],
+                                     id,
                                      0,
                                      closure,
                                      FALSE);
@@ -1274,10 +1322,19 @@ dbus_g_connection_register_g_object (DBusGConnection       *connection,
                                      const char            *at_path,
                                      GObject               *object)
 {
+  const DBusGObjectInfo *info;
   g_return_if_fail (connection != NULL);
   g_return_if_fail (at_path != NULL);
   g_return_if_fail (G_IS_OBJECT (object));
 
+  info = lookup_object_info (object);
+  if (info == NULL)
+    {
+      g_warning ("No introspection data registered for object class \"%s\"",
+                g_type_name (G_TYPE_FROM_INSTANCE (object)));
+      return;
+    }
+
   if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
                                              at_path,
                                              &gobject_dbus_vtable,
@@ -1287,7 +1344,7 @@ dbus_g_connection_register_g_object (DBusGConnection       *connection,
       return;
     }
 
-  export_signals (connection, object);
+  export_signals (connection, info, object);
 
   g_object_set_data (object, "dbus_glib_object_path", g_strdup (at_path));
   g_object_weak_ref (object, (GWeakNotify)unregister_gobject, connection);
@@ -1337,7 +1394,7 @@ funcsig_equal (gconstpointer aval,
   const DBusGFuncSignature *b = bval;
   const GType *atypes;
   const GType *btypes;
-  guint i, j;
+  guint i;
 
   if (a->rettype != b->rettype
       || a->n_params != b->n_params)
@@ -1422,22 +1479,56 @@ _dbus_gobject_lookup_marshaller (GType        rettype,
 }
 
 /**
- * Register a GClosureMarshal to be used for signal invocations.
+ * Register a GClosureMarshal to be used for signal invocations,
+ * giving its return type and a list of parameter types,
+ * followed by G_TYPE_INVALID.
+
  * This function will not be needed once GLib includes libffi.
  *
+ * @param marshaller a GClosureMarshal to be used for invocation
+ * @param rettype a GType for the return type of the function
+ * @param ... The parameter GTypes, followed by G_TYPE_INVALID
+ */
+void
+dbus_g_object_register_marshaller (GClosureMarshal  marshaller,
+                                  GType            rettype,
+                                  ...)
+{
+  va_list args;
+  GArray *types;
+  GType gtype;
+
+  va_start (args, rettype);
+
+  types = g_array_new (TRUE, TRUE, sizeof (GType));
+
+  while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
+    g_array_append_val (types, gtype);
+
+  dbus_g_object_register_marshaller_array (marshaller, rettype,
+                                          types->len, (GType*) types->data);
+
+  g_array_free (types, TRUE);
+  va_end (args);
+}
+
+/**
+ * Register a GClosureMarshal to be used for signal invocations.
+ * See also #dbus_g_object_register_marshaller
+ *
+ * @param marshaller a GClosureMarshal to be used for invocation
  * @param rettype a GType for the return type of the function
  * @param n_types number of function parameters
  * @param param_types a C array of GTypes values
- * @param marshaller a GClosureMarshal to be used for invocation
  */
 void
-dbus_g_object_register_marshaller (GType            rettype,
-                                  guint            n_types,
-                                  const GType      *param_types,
-                                  GClosureMarshal   marshaller)
+dbus_g_object_register_marshaller_array (GClosureMarshal  marshaller,
+                                        GType            rettype,
+                                        guint            n_types,
+                                        const GType*     types)
 {
   DBusGFuncSignature *sig;
-  
+
   g_static_rw_lock_writer_lock (&globals_lock);
 
   if (marshal_table == NULL)
@@ -1449,7 +1540,7 @@ dbus_g_object_register_marshaller (GType            rettype,
   sig->rettype = rettype;
   sig->n_params = n_types;
   sig->params = g_new (GType, n_types);
-  memcpy (sig->params, param_types, n_types * sizeof (GType));
+  memcpy (sig->params, types, n_types * sizeof (GType));
 
   g_hash_table_insert (marshal_table, sig, marshaller);
 
index 836167efa3f89a9728f36f4981b1f29b2d8111dc..8c683af4ca3865dc2647d395cd85d9933bae5275 100644 (file)
@@ -934,9 +934,12 @@ dbus_g_proxy_emit_remote_signal (DBusGProxy  *proxy,
   g_free (name);
   return;
  mismatch:
+#if 0
+  /* Don't spew on remote errors */
   g_warning ("Unexpected message signature '%s' for signal '%s'\n",
             dbus_message_get_signature (message),
             name);
+#endif
   goto out;
 }
 
index cdaabeb93dcee600b1e9633889ed8c960de0dbe3..a0cd5e95b42d07ded9c1db213a89c9c6611a70e5 100644 (file)
@@ -11,3 +11,5 @@ run-test.conf
 test-service-glib-bindings.h
 test-service-glib-glue.h
 run-with-tmp-session-bus.conf
+my-object-marshal.h
+my-object-marshal.c
index 568dab3d6655bcfb7e43491e33dc64018d07213f..77ee19061fa651f7eba0deadc292b3bfd8f0a575 100644 (file)
@@ -35,14 +35,16 @@ endif
 noinst_PROGRAMS= test-dbus-glib test-service-glib $(THREAD_APPS)
 
 test_dbus_glib_SOURCES=                                \
+       my-object-marshal.c                             \
        test-dbus-glib.c
 
 test_dbus_glib_LDADD= $(DBUS_GLIB_TOOL_LIBS) $(top_builddir)/glib/libdbus-glib-1.la $(top_builddir)/glib/libdbus-gtool.la
 
-test_service_glib_SOURCES=                             \
-       test-service-glib.c
+BUILT_SOURCES = test-service-glib-glue.h test-service-glib-bindings.h my-object-marshal.c my-object-marshal.h 
 
-BUILT_SOURCES = test-service-glib-glue.h test-service-glib-bindings.h
+test_service_glib_SOURCES=                             \
+       my-object-marshal.c                             \
+       test-service-glib.c 
 
 test-service-glib-glue.h: test-service-glib.xml $(top_builddir)/glib/dbus-binding-tool
        $(top_builddir)/glib/dbus-binding-tool --prefix=my_object --mode=glib-server --output=test-service-glib-glue.h $(srcdir)/test-service-glib.xml
@@ -50,7 +52,14 @@ test-service-glib-glue.h: test-service-glib.xml $(top_builddir)/glib/dbus-bindin
 test-service-glib-bindings.h: test-service-glib.xml $(top_builddir)/glib/dbus-binding-tool
        $(top_builddir)/glib/dbus-binding-tool --prefix=my_object --mode=glib-client --output=test-service-glib-bindings.h $(srcdir)/test-service-glib.xml
 
-CLEANFILES = test-service-glib-glue.h test-service-glib-bindings.h
+my-object-marshal.c: Makefile my-object-marshal.list
+       @GLIB_GENMARSHAL@ --prefix=my_object_marshal $(srcdir)/my-object-marshal.list --header --body > my-object-marshal.c
+
+my-object-marshal.h: Makefile my-object-marshal.list
+       @GLIB_GENMARSHAL@ --prefix=my_object_marshal $(srcdir)/my-object-marshal.list --header > my-object-marshal.h
+
+
+CLEANFILES = $(BUILT_SOURCES)
 
 test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la
 
diff --git a/test/glib/my-object-marshal.list b/test/glib/my-object-marshal.list
new file mode 100644 (file)
index 0000000..48cbfad
--- /dev/null
@@ -0,0 +1,2 @@
+NONE:STRING,INT,STRING
+NONE:STRING,BOXED
index 2fc8665b5efd36424b21e2e923112d3875948400..1f979a27c98bd5023569868965a0a92447681997 100644 (file)
@@ -7,10 +7,14 @@
 #include <glib/dbus-gidl.h>
 #include <glib/dbus-gparser.h>
 #include <glib-object.h>
+#include "my-object-marshal.h"
 
 static GMainLoop *loop = NULL;
 static int n_times_foo_received = 0;
 static int n_times_frobnicate_received = 0;
+static int n_times_sig0_received = 0;
+static int n_times_sig1_received = 0;
+static guint exit_timeout = 0;
 
 static gboolean
 timed_exit (gpointer loop)
@@ -27,6 +31,7 @@ foo_signal_handler (DBusGProxy  *proxy,
   n_times_foo_received += 1;
 
   g_main_loop_quit (loop);
+  g_source_remove (exit_timeout);
 }
 
 static void
@@ -39,6 +44,44 @@ frobnicate_signal_handler (DBusGProxy  *proxy,
   g_assert (val == 42);
 
   g_main_loop_quit (loop);
+  g_source_remove (exit_timeout);
+}
+
+static void
+sig0_signal_handler (DBusGProxy  *proxy,
+                    const char  *str0,
+                    int          val,
+                    const char  *str1,
+                    void        *user_data)
+{
+  n_times_sig0_received += 1;
+
+  g_assert (!strcmp (str0, "foo"));
+
+  g_assert (val == 22);
+
+  g_assert (!strcmp (str1, "moo"));
+
+  g_main_loop_quit (loop);
+  g_source_remove (exit_timeout);
+}
+
+static void
+sig1_signal_handler (DBusGProxy  *proxy,
+                    const char  *str0,
+                    GValue      *value,
+                    void        *user_data)
+{
+  n_times_sig1_received += 1;
+
+  g_assert (!strcmp (str0, "baz"));
+
+  g_assert (G_VALUE_HOLDS_STRING (value));
+
+  g_assert (!strcmp (g_value_get_string (value), "bar"));
+
+  g_main_loop_quit (loop);
+  g_source_remove (exit_timeout);
 }
 
 static void lose (const char *fmt, ...) G_GNUC_NORETURN G_GNUC_PRINTF (1, 2);
@@ -216,9 +259,7 @@ main (int argc, char **argv)
                               G_TYPE_INVALID);
   
   dbus_g_connection_flush (connection);
-  
-  g_timeout_add (5000, timed_exit, loop);
-
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
   g_main_loop_run (loop);
 
   if (n_times_foo_received != 1)
@@ -643,16 +684,81 @@ main (int argc, char **argv)
 
   
   dbus_g_connection_flush (connection);
-  
-#if 0
-  g_timeout_add (5000, timed_exit, loop);
-
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
   g_main_loop_run (loop);
 
   if (n_times_frobnicate_received != 1)
     lose ("Frobnicate signal received %d times, should have been 1", n_times_frobnicate_received);
-#endif
 
+  if (!dbus_g_proxy_invoke (proxy, "EmitFrobnicate", &error,
+                           G_TYPE_INVALID, G_TYPE_INVALID))
+    lose_gerror ("Failed to complete EmitFrobnicate call", error);
+  
+  dbus_g_connection_flush (connection);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+
+  if (n_times_frobnicate_received != 2)
+    lose ("Frobnicate signal received %d times, should have been 2", n_times_frobnicate_received);
+
+  g_object_unref (G_OBJECT (proxy));
+
+  proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                           "org.freedesktop.DBus.TestSuiteGLibService",
+                                           "/org/freedesktop/DBus/Tests/MyTestObject",
+                                           "org.freedesktop.DBus.Tests.FooObject",
+                                           &error);
+  
+  if (proxy == NULL)
+    lose_gerror ("Failed to create proxy for name owner", error);
+
+  dbus_g_object_register_marshaller (my_object_marshal_VOID__STRING_INT_STRING, 
+                                    G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID);
+
+  dbus_g_object_register_marshaller (my_object_marshal_VOID__STRING_BOXED, 
+                                    G_TYPE_NONE, G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
+
+  dbus_g_proxy_add_signal (proxy, "Sig0", G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID);
+  dbus_g_proxy_add_signal (proxy, "Sig1", G_TYPE_STRING, G_TYPE_VALUE);
+  
+  dbus_g_proxy_connect_signal (proxy, "Sig0",
+                               G_CALLBACK (sig0_signal_handler),
+                               NULL, NULL);
+  dbus_g_proxy_connect_signal (proxy, "Sig1",
+                               G_CALLBACK (sig1_signal_handler),
+                               NULL, NULL);
+
+  dbus_g_proxy_call_no_reply (proxy, "EmitSignals", G_TYPE_INVALID);
+
+  dbus_g_connection_flush (connection);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+
+  if (n_times_sig0_received != 1)
+    lose ("Sig0 signal received %d times, should have been 1", n_times_sig0_received);
+  if (n_times_sig1_received != 1)
+    lose ("Sig1 signal received %d times, should have been 1", n_times_sig1_received);
+
+  dbus_g_proxy_call_no_reply (proxy, "EmitSignals", G_TYPE_INVALID);
+  dbus_g_proxy_call_no_reply (proxy, "EmitSignals", G_TYPE_INVALID);
+
+  dbus_g_connection_flush (connection);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+
+  if (n_times_sig0_received != 3)
+    lose ("Sig0 signal received %d times, should have been 3", n_times_sig0_received);
+  if (n_times_sig1_received != 3)
+    lose ("Sig1 signal received %d times, should have been 3", n_times_sig1_received);
+  
   g_object_unref (G_OBJECT (proxy));
 
   proxy = dbus_g_proxy_new_for_name_owner (connection,
@@ -680,7 +786,6 @@ main (int argc, char **argv)
     gboolean found_properties;
     gboolean found_myobject;
     gboolean found_fooobject;
-    gboolean found_gtk_myobject;
 
     node = description_load_from_string (v_STRING_2, strlen (v_STRING_2), &error);
     if (!node)
@@ -688,7 +793,6 @@ main (int argc, char **argv)
 
     found_introspectable = FALSE;
     found_properties = FALSE;
-    found_gtk_myobject = FALSE;
     found_myobject = FALSE;
     found_fooobject = FALSE;
     for (elt = node_info_get_interfaces (node); elt ; elt = elt->next)
@@ -699,8 +803,6 @@ main (int argc, char **argv)
          found_introspectable = TRUE;
        else if (!found_properties && strcmp (interface_info_get_name (iface), "org.freedesktop.DBus.Properties") == 0)
          found_properties = TRUE;
-       else if (strcmp (interface_info_get_name (iface), "org.gtk.objects.MyObject") == 0)
-         found_gtk_myobject = TRUE;
        else if (!found_myobject && strcmp (interface_info_get_name (iface), "org.freedesktop.DBus.Tests.MyObject") == 0)
          {
            GSList *elt;
@@ -729,7 +831,7 @@ main (int argc, char **argv)
          lose ("Unexpected or duplicate interface %s", interface_info_get_name (iface));
       }
 
-    if (!(found_introspectable && found_gtk_myobject && found_myobject && found_properties))
+    if (!(found_introspectable && found_myobject && found_properties))
       lose ("Missing interface"); 
   }
   g_free (v_STRING_2);
index 208bfb2478ff612fa964dae5ffc723b8d2d73d18..6089367efbd37e8c11e91a5efc855355bf5b3797 100644 (file)
@@ -10,6 +10,7 @@
 #include <glib/gi18n.h>
 #include <glib-object.h>
 #include <glib/gquark.h>
+#include "my-object-marshal.h"
 
 typedef struct MyObject MyObject;
 typedef struct MyObjectClass MyObjectClass;
@@ -77,6 +78,8 @@ gboolean my_object_get_val (MyObject *obj, guint *ret, GError **error);
 
 gboolean my_object_get_value (MyObject *obj, guint *ret, GError **error);
 
+gboolean my_object_emit_signals (MyObject *obj, GError **error);
+
 gboolean my_object_emit_frobnicate (MyObject *obj, GError **error);
 
 #include "test-service-glib-glue.h"
@@ -93,10 +96,11 @@ enum
 enum
 {
   FROBNICATE,
+  SIG0,
+  SIG1,
   LAST_SIGNAL
 };
 
-static void *parent_class;
 static guint signals[LAST_SIGNAL] = { 0 };
 
 static void
@@ -185,6 +189,23 @@ my_object_class_init (MyObjectClass *mobject_class)
                   g_cclosure_marshal_VOID__INT,
                   G_TYPE_NONE, 1, G_TYPE_INT);
 
+  signals[SIG0] =
+    g_signal_new ("sig0",
+                 G_OBJECT_CLASS_TYPE (mobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+                  0,
+                  NULL, NULL,
+                  my_object_marshal_VOID__STRING_INT_STRING,
+                  G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
+
+  signals[SIG1] =
+    g_signal_new ("sig1",
+                 G_OBJECT_CLASS_TYPE (mobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+                  0,
+                  NULL, NULL,
+                  my_object_marshal_VOID__STRING_BOXED,
+                  G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VALUE);
 }
 
 GQuark
@@ -403,6 +424,21 @@ my_object_emit_frobnicate (MyObject *obj, GError **error)
   return TRUE;
 }
 
+gboolean
+my_object_emit_signals (MyObject *obj, GError **error)
+{
+  GValue val = {0, };
+
+  g_signal_emit (obj, signals[SIG0], 0, "foo", 22, "moo");
+
+  g_value_init (&val, G_TYPE_STRING);
+  g_value_set_string (&val, "bar");
+  g_signal_emit (obj, signals[SIG1], 0, "baz", &val);
+  g_value_unset (&val);
+
+  return TRUE;
+}
+
 static GMainLoop *loop;
 
 #define TEST_SERVICE_NAME "org.freedesktop.DBus.TestSuiteGLibService"
index f976572b8614a130e8982c66c7ea63c495c21efb..05cb5abdaec1a42e4ba3184dc981cc8d51cfa147 100644 (file)
     <method name="EmitFrobnicate">
     </method>
 
+    <!-- Export signals -->
+    <signal name="Frobnicate"/>
   </interface>
 
+  <!-- Test multiple interfaces on the same object -->
+
   <interface name="org.freedesktop.DBus.Tests.FooObject">
     <method name="GetValue">
       <arg type="u" direction="out" />
     </method>
 
+    <method name="EmitSignals">
+    </method>
+
+    <signal name="Sig0"/>
+
+    <signal name="Sig1"/>
+
   </interface>
 
 </node>