summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2005-06-17 14:29:48 +0000
committerColin Walters <walters@verbum.org>2005-06-17 14:29:48 +0000
commit949436ffac9e46649398e1bc9f0ddf567c88dd1c (patch)
treed8bad3f3ffa5813a7e99726b66bba3de8aafc319
parent679018f00c7277ecd6272cb1be5dfdedf134c422 (diff)
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.
-rw-r--r--ChangeLog62
-rw-r--r--dbus/dbus-glib.h19
-rw-r--r--doc/TODO5
-rw-r--r--glib/dbus-binding-tool-glib.c88
-rw-r--r--glib/dbus-gobject.c547
-rw-r--r--glib/dbus-gproxy.c3
-rw-r--r--test/glib/.cvsignore2
-rw-r--r--test/glib/Makefile.am17
-rw-r--r--test/glib/my-object-marshal.list2
-rw-r--r--test/glib/test-dbus-glib.c128
-rw-r--r--test/glib/test-service-glib.c38
-rw-r--r--test/glib/test-service-glib.xml11
12 files changed, 648 insertions, 274 deletions
diff --git a/ChangeLog b/ChangeLog
index 2f6b058c..8b4f8796 100644
--- 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.
diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h
index 80ed7f4f..4debe6fe 100644
--- a/dbus/dbus-glib.h
+++ b/dbus/dbus-glib.h
@@ -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;
diff --git a/doc/TODO b/doc/TODO
index 3c0e6cb3..4b953bad 100644
--- 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
diff --git a/glib/dbus-binding-tool-glib.c b/glib/dbus-binding-tool-glib.c
index b04386bc..fd849a86 100644
--- a/glib/dbus-binding-tool-glib.c
+++ b/glib/dbus-binding-tool-glib.c
@@ -48,6 +48,8 @@ typedef struct
GHashTable *generated;
GString *blob;
+ GString *signal_blob;
+ GString *property_blob;
guint count;
} DBusBindingToolCData;
@@ -365,13 +367,37 @@ write_printf_to_iochannel (const char *fmt, GIOChannel *channel, GError **error,
}
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)
{
if (base_info_get_type (base) == INFO_TYPE_NODE)
{
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:
diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c
index 7a57d4ea..40d1da03 100644
--- a/glib/dbus-gobject.c
+++ b/glib/dbus-gobject.c
@@ -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);
diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c
index 836167ef..8c683af4 100644
--- a/glib/dbus-gproxy.c
+++ b/glib/dbus-gproxy.c
@@ -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;
}
diff --git a/test/glib/.cvsignore b/test/glib/.cvsignore
index cdaabeb9..a0cd5e95 100644
--- a/test/glib/.cvsignore
+++ b/test/glib/.cvsignore
@@ -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
diff --git a/test/glib/Makefile.am b/test/glib/Makefile.am
index 568dab3d..77ee1906 100644
--- a/test/glib/Makefile.am
+++ b/test/glib/Makefile.am
@@ -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
index 00000000..48cbfad4
--- /dev/null
+++ b/test/glib/my-object-marshal.list
@@ -0,0 +1,2 @@
+NONE:STRING,INT,STRING
+NONE:STRING,BOXED
diff --git a/test/glib/test-dbus-glib.c b/test/glib/test-dbus-glib.c
index 2fc8665b..1f979a27 100644
--- a/test/glib/test-dbus-glib.c
+++ b/test/glib/test-dbus-glib.c
@@ -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);
diff --git a/test/glib/test-service-glib.c b/test/glib/test-service-glib.c
index 208bfb24..6089367e 100644
--- a/test/glib/test-service-glib.c
+++ b/test/glib/test-service-glib.c
@@ -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"
diff --git a/test/glib/test-service-glib.xml b/test/glib/test-service-glib.xml
index f976572b..05cb5abd 100644
--- a/test/glib/test-service-glib.xml
+++ b/test/glib/test-service-glib.xml
@@ -84,13 +84,24 @@
<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>