mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 14:38:10 +02:00
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.
This commit is contained in:
parent
679018f00c
commit
949436ffac
12 changed files with 660 additions and 286 deletions
62
ChangeLog
62
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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
5
doc/TODO
5
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -204,6 +204,49 @@ method_output_signature_from_object_info (const DBusGObjectInfo *object,
|
|||
return method_dir_signature_from_object_info (object, method, FALSE);
|
||||
}
|
||||
|
||||
static const char *
|
||||
propsig_iterate (const char *data, const char **iface, const char **name)
|
||||
{
|
||||
*iface = data;
|
||||
|
||||
data = string_table_next (data);
|
||||
*name = data;
|
||||
|
||||
return string_table_next (data);
|
||||
}
|
||||
|
||||
static const DBusGObjectInfo *
|
||||
lookup_object_info (GObject *object)
|
||||
{
|
||||
const DBusGObjectInfo *ret;
|
||||
GType classtype;
|
||||
|
||||
ret = NULL;
|
||||
|
||||
g_static_rw_lock_reader_lock (&globals_lock);
|
||||
|
||||
if (info_hash == NULL)
|
||||
goto out;
|
||||
|
||||
for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
|
||||
{
|
||||
const DBusGObjectInfo *info;
|
||||
|
||||
info = g_hash_table_lookup (info_hash, g_type_class_peek (classtype));
|
||||
|
||||
if (info != NULL && info->format_version == 0)
|
||||
{
|
||||
ret = info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
g_static_rw_lock_reader_unlock (&globals_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gobject_unregister_function (DBusConnection *connection,
|
||||
void *user_data)
|
||||
|
|
@ -216,148 +259,39 @@ gobject_unregister_function (DBusConnection *connection,
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
introspect_properties (GObject *object, GString *xml)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int n_specs;
|
||||
GType last_type;
|
||||
GParamSpec **specs;
|
||||
|
||||
last_type = G_TYPE_INVALID;
|
||||
specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object),
|
||||
&n_specs);
|
||||
|
||||
for (i = 0; i < n_specs; i++ )
|
||||
{
|
||||
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");
|
||||
|
||||
|
||||
/* 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");
|
||||
|
||||
last_type = spec->owner_type;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
g_free (specs);
|
||||
}
|
||||
|
||||
static void
|
||||
introspect_signals (GType type, GString *xml)
|
||||
{
|
||||
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]);
|
||||
|
||||
if (!dbus_type)
|
||||
continue;
|
||||
|
||||
g_string_append (xml, " <arg type=\"");
|
||||
g_string_append (xml, dbus_type);
|
||||
g_string_append (xml, "\"/>\n");
|
||||
}
|
||||
|
||||
g_string_append (xml, " </signal>\n");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
data.xml = xml;
|
||||
data.object_info = info;
|
||||
g_hash_table_foreach (interfaces, write_interface, &data);
|
||||
|
||||
g_hash_table_destroy (interfaces);
|
||||
}
|
||||
values = lookup_values (interfaces, method_interface);
|
||||
values->methods = g_slist_prepend (values->methods, (gpointer) method);
|
||||
}
|
||||
|
||||
g_static_rw_lock_reader_unlock (&globals_lock);
|
||||
propsig = info->exported_signals;
|
||||
while (*propsig)
|
||||
{
|
||||
const char *iface;
|
||||
const char *signame;
|
||||
|
||||
propsig = propsig_iterate (propsig, &iface, &signame);
|
||||
|
||||
values = lookup_values (interfaces, iface);
|
||||
values->signals = g_slist_prepend (values->signals, (gpointer) signame);
|
||||
}
|
||||
|
||||
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;
|
||||
const char *expected_member;
|
||||
const char *expected_interface;
|
||||
char *expected_signature;
|
||||
const DBusGMethodInfo *method;
|
||||
|
||||
info = g_hash_table_lookup (info_hash,
|
||||
g_type_class_peek (classtype));
|
||||
method = &(info->method_infos[i]);
|
||||
|
||||
*object_ret = info;
|
||||
/* 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 (info != NULL && info->format_version == 0)
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
2
test/glib/my-object-marshal.list
Normal file
2
test/glib/my-object-marshal.list
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
NONE:STRING,INT,STRING
|
||||
NONE:STRING,BOXED
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue