1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gobject.c Exporting a GObject remotely
4 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
5 * Copyright (C) 2005 Nokia
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <gobject/gvaluecollector.h>
27 #include <dbus/dbus-glib.h>
28 #include <dbus/dbus-glib-lowlevel.h>
29 #include "dbus-gtest.h"
30 #include "dbus-gutils.h"
31 #include "dbus-gobject.h"
32 #include "dbus-gsignature.h"
33 #include "dbus-gvalue.h"
34 #include "dbus-gmarshal.h"
35 #include "dbus-gvalue-utils.h"
39 * @addtogroup DBusGLibInternals
49 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
50 static GHashTable *marshal_table = NULL;
51 static GData *error_metadata = NULL;
54 uscore_to_wincaps (const char *uscore)
58 gboolean last_was_uscore;
60 last_was_uscore = TRUE;
62 str = g_string_new (NULL);
66 if (*p == '-' || *p == '_')
68 last_was_uscore = TRUE;
74 g_string_append_c (str, g_ascii_toupper (*p));
75 last_was_uscore = FALSE;
78 g_string_append_c (str, *p);
83 return g_string_free (str, FALSE);
87 string_table_next (const char *table)
89 return (table + (strlen (table) + 1));
93 string_table_lookup (const char *table, int index)
100 ret = string_table_next (ret);
106 get_method_data (const DBusGObjectInfo *object,
107 const DBusGMethodInfo *method)
109 return object->data + method->data_offset;
113 object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
120 object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
127 method_interface_from_object_info (const DBusGObjectInfo *object,
128 const DBusGMethodInfo *method)
130 return string_table_lookup (get_method_data (object, method), 0);
134 method_name_from_object_info (const DBusGObjectInfo *object,
135 const DBusGMethodInfo *method)
137 return string_table_lookup (get_method_data (object, method), 1);
141 method_arg_info_from_object_info (const DBusGObjectInfo *object,
142 const DBusGMethodInfo *method)
144 return string_table_lookup (get_method_data (object, method), 3);/*RB was 2*/
155 arg_iterate (const char *data,
167 data = string_table_next (data);
177 g_warning ("invalid arg direction '%c'", *data);
186 data = string_table_next (data);
198 g_warning ("invalid arg const value '%c'", *data);
201 data = string_table_next (data);
206 *retval = RETVAL_NONE;
210 *retval = RETVAL_ERROR;
214 *retval = RETVAL_NOERROR;
217 g_warning ("invalid arg ret value '%c'", *data);
229 data = string_table_next (data);
233 return string_table_next (data);
237 method_dir_signature_from_object_info (const DBusGObjectInfo *object,
238 const DBusGMethodInfo *method,
244 arg = method_arg_info_from_object_info (object, method);
246 ret = g_string_new (NULL);
254 arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
257 g_string_append (ret, type);
260 return g_string_free (ret, FALSE);
264 method_input_signature_from_object_info (const DBusGObjectInfo *object,
265 const DBusGMethodInfo *method)
267 return method_dir_signature_from_object_info (object, method, TRUE);
271 method_output_signature_from_object_info (const DBusGObjectInfo *object,
272 const DBusGMethodInfo *method)
274 return method_dir_signature_from_object_info (object, method, FALSE);
278 propsig_iterate (const char *data, const char **iface, const char **name)
282 data = string_table_next (data);
285 return string_table_next (data);
289 dbus_g_object_type_dbus_metadata_quark (void)
294 quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
298 static const DBusGObjectInfo *
299 lookup_object_info (GObject *object)
301 const DBusGObjectInfo *ret;
306 for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
308 const DBusGObjectInfo *info;
310 info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
312 if (info != NULL && info->format_version >= 0)
323 gobject_unregister_function (DBusConnection *connection,
328 object = G_OBJECT (user_data);
338 const DBusGObjectInfo *object_info;
339 } DBusGLibWriteIterfaceData;
346 } DBusGLibWriteInterfaceValues;
349 write_interface (gpointer key, gpointer val, gpointer user_data)
356 const DBusGObjectInfo *object_info;
357 DBusGLibWriteIterfaceData *data;
358 DBusGLibWriteInterfaceValues *values;
363 methods = values->methods;
364 signals = values->signals;
365 properties = values->properties;
369 object_info = data->object_info;
371 g_string_append_printf (xml, " <interface name=\"%s\">\n", name);
373 /* FIXME: recurse to parent types ? */
374 for (; methods; methods = methods->next)
376 DBusGMethodInfo *method;
378 method = methods->data;
380 g_string_append_printf (xml, " <method name=\"%s\">\n",
381 method_name_from_object_info (object_info, method));
383 args = method_arg_info_from_object_info (object_info, method);
391 args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
393 /* FIXME - handle container types */
394 g_string_append_printf (xml, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
395 name, type, arg_in ? "in" : "out");
398 g_string_append (xml, " </method>\n");
401 g_slist_free (values->methods);
403 for (; signals; signals = signals->next)
411 signame = signals->data;
413 s = _dbus_gutils_wincaps_to_uscore (signame);
415 id = g_signal_lookup (s, data->gtype);
418 g_signal_query (id, &query);
419 g_assert (query.return_type == G_TYPE_NONE);
421 g_string_append_printf (xml, " <signal name=\"%s\">\n", signame);
423 for (arg = 0; arg < query.n_params; arg++)
425 char *dbus_type = _dbus_gtype_to_signature (query.param_types[arg]);
427 g_assert (dbus_type != NULL);
429 g_string_append (xml, " <arg type=\"");
430 g_string_append (xml, dbus_type);
431 g_string_append (xml, "\"/>\n");
435 g_string_append (xml, " </signal>\n");
438 g_slist_free (values->signals);
440 for (; properties; properties = properties->next)
442 const char *propname;
449 propname = properties->data;
452 s = _dbus_gutils_wincaps_to_uscore (spec->name);
454 spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
455 g_assert (spec != NULL);
458 dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
459 g_assert (dbus_type != NULL);
461 can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
462 (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
464 can_get = (spec->flags & G_PARAM_READABLE) != 0;
466 if (can_set || can_get)
468 g_string_append_printf (xml, " <property name=\"%s\" ", propname);
469 g_string_append (xml, "type=\"");
470 g_string_append (xml, dbus_type);
471 g_string_append (xml, "\" access=\"");
473 if (can_set && can_get)
474 g_string_append (xml, "readwrite");
476 g_string_append (xml, "read");
480 g_string_append (xml, "write");
483 g_string_append (xml, "\"/>\n");
489 g_string_append (xml, " </property>\n");
491 g_slist_free (values->properties);
494 g_string_append (xml, " </interface>\n");
497 static DBusGLibWriteInterfaceValues *
498 lookup_values (GHashTable *interfaces, const char *method_interface)
500 DBusGLibWriteInterfaceValues *values;
501 if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
503 values = g_new0 (DBusGLibWriteInterfaceValues, 1);
504 g_hash_table_insert (interfaces, (gpointer) method_interface, values);
510 introspect_interfaces (GObject *object, GString *xml)
512 const DBusGObjectInfo *info;
513 DBusGLibWriteIterfaceData data;
515 GHashTable *interfaces;
516 DBusGLibWriteInterfaceValues *values;
519 info = lookup_object_info (object);
521 g_assert (info != NULL);
523 /* Gather a list of all interfaces, indexed into their methods */
524 interfaces = g_hash_table_new (g_str_hash, g_str_equal);
525 for (i = 0; i < info->n_method_infos; i++)
527 const char *method_name;
528 const char *method_interface;
529 const char *method_args;
530 const DBusGMethodInfo *method;
532 method = &(info->method_infos[i]);
534 method_interface = method_interface_from_object_info (info, method);
535 method_name = method_name_from_object_info (info, method);
536 method_args = method_arg_info_from_object_info (info, method);
538 values = lookup_values (interfaces, method_interface);
539 values->methods = g_slist_prepend (values->methods, (gpointer) method);
542 propsig = info->exported_signals;
548 propsig = propsig_iterate (propsig, &iface, &signame);
550 values = lookup_values (interfaces, iface);
551 values->signals = g_slist_prepend (values->signals, (gpointer) signame);
554 propsig = info->exported_properties;
558 const char *propname;
560 propsig = propsig_iterate (propsig, &iface, &propname);
562 values = lookup_values (interfaces, iface);
563 values->properties = g_slist_prepend (values->properties, (gpointer) propname);
566 memset (&data, 0, sizeof (data));
568 data.gtype = G_TYPE_FROM_INSTANCE (object);
569 data.object_info = info;
570 g_hash_table_foreach (interfaces, write_interface, &data);
572 g_hash_table_destroy (interfaces);
575 static DBusHandlerResult
576 handle_introspect (DBusConnection *connection,
577 DBusMessage *message,
585 if (!dbus_connection_list_registered (connection,
586 dbus_message_get_path (message),
588 g_error ("Out of memory");
590 xml = g_string_new (NULL);
592 g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
594 g_string_append (xml, "<node>\n");
596 /* We are introspectable, though I guess that was pretty obvious */
597 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE);
598 g_string_append (xml, " <method name=\"Introspect\">\n");
599 g_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
600 g_string_append (xml, " </method>\n");
601 g_string_append (xml, " </interface>\n");
603 /* We support get/set properties */
604 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_PROPERTIES);
605 g_string_append (xml, " <method name=\"Get\">\n");
606 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
607 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
608 g_string_append_printf (xml, " <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
609 g_string_append (xml, " </method>\n");
610 g_string_append (xml, " <method name=\"Set\">\n");
611 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
612 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
613 g_string_append_printf (xml, " <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
614 g_string_append (xml, " </method>\n");
615 g_string_append (xml, " </interface>\n");
617 introspect_interfaces (object, xml);
619 /* Append child nodes */
620 for (i = 0; children[i]; i++)
621 g_string_append_printf (xml, " <node name=\"%s\"/>\n",
624 /* Close the XML, and send it to the requesting app */
625 g_string_append (xml, "</node>\n");
627 ret = dbus_message_new_method_return (message);
629 g_error ("Out of memory");
631 dbus_message_append_args (ret,
632 DBUS_TYPE_STRING, &xml->str,
635 dbus_connection_send (connection, ret, NULL);
636 dbus_message_unref (ret);
638 g_string_free (xml, TRUE);
640 dbus_free_string_array (children);
642 return DBUS_HANDLER_RESULT_HANDLED;
646 set_object_property (DBusConnection *connection,
647 DBusMessage *message,
648 DBusMessageIter *iter,
652 GValue value = { 0, };
655 DBusGValueMarshalCtx context;
657 dbus_message_iter_recurse (iter, &sub);
659 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
660 context.proxy = NULL;
662 g_value_init (&value, pspec->value_type);
663 if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
665 g_object_set_property (object,
669 g_value_unset (&value);
671 ret = dbus_message_new_method_return (message);
673 g_error ("out of memory");
677 ret = dbus_message_new_error (message,
678 DBUS_ERROR_INVALID_ARGS,
679 "Argument's D-BUS type can't be converted to a GType");
681 g_error ("out of memory");
688 get_object_property (DBusConnection *connection,
689 DBusMessage *message,
694 GValue value = {0, };
696 DBusMessageIter iter;
698 value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
700 ret = dbus_message_new_method_return (message);
702 g_error ("out of memory");
704 g_value_init (&value, value_type);
705 g_object_get_property (object, pspec->name, &value);
707 value_type = G_VALUE_TYPE (&value);
709 dbus_message_iter_init_append (message, &iter);
711 if (!_dbus_gvalue_marshal (&iter, &value))
713 dbus_message_unref (ret);
714 ret = dbus_message_new_error (message,
715 DBUS_ERROR_UNKNOWN_METHOD,
716 "Can't convert GType of object property to a D-BUS type");
723 lookup_object_and_method (GObject *object,
724 DBusMessage *message,
725 const DBusGObjectInfo **object_ret,
726 const DBusGMethodInfo **method_ret)
728 const char *interface;
730 const char *signature;
732 const DBusGObjectInfo *info;
735 interface = dbus_message_get_interface (message);
736 member = dbus_message_get_member (message);
737 signature = dbus_message_get_signature (message);
740 info = lookup_object_info (object);
743 for (i = 0; i < info->n_method_infos; i++)
745 const char *expected_member;
746 const char *expected_interface;
747 char *expected_signature;
748 const DBusGMethodInfo *method;
750 method = &(info->method_infos[i]);
752 /* Check method interface/name and input signature */
753 expected_interface = method_interface_from_object_info (*object_ret, method);
754 expected_member = method_name_from_object_info (*object_ret, method);
755 expected_signature = method_input_signature_from_object_info (*object_ret, method);
757 if ((interface == NULL
758 || strcmp (expected_interface, interface) == 0)
759 && strcmp (expected_member, member) == 0
760 && strcmp (expected_signature, signature) == 0)
762 g_free (expected_signature);
763 *method_ret = method;
766 g_free (expected_signature);
773 gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
774 const char *msg_interface,
775 GQuark domain, gint code)
777 const char *domain_str;
778 const char *code_str;
779 GString *dbus_error_name;
781 domain_str = object_error_domain_prefix_from_object_info (object_info);
782 code_str = object_error_code_from_object_info (object_info, domain, code);
784 if (!domain_str || !code_str)
786 DBusGErrorInfo *info;
788 g_static_rw_lock_reader_lock (&globals_lock);
790 if (error_metadata != NULL)
791 info = g_datalist_id_get_data (&error_metadata, domain);
795 g_static_rw_lock_reader_unlock (&globals_lock);
802 klass = g_type_class_ref (info->code_enum);
803 value = g_enum_get_value (klass, code);
804 g_type_class_unref (klass);
806 domain_str = info->default_iface;
807 code_str = value->value_nick;
812 domain_str = msg_interface;
814 if (!domain_str || !code_str)
816 /* If we can't map it sensibly, make up an error name */
817 char *domain_from_quark;
819 dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
821 domain_from_quark = uscore_to_wincaps (g_quark_to_string (domain));
822 g_string_append (dbus_error_name, domain_from_quark);
823 g_free (domain_from_quark);
825 g_string_append_printf (dbus_error_name, ".Code%d", code);
829 dbus_error_name = g_string_new (domain_str);
830 g_string_append_c (dbus_error_name, '.');
831 g_string_append (dbus_error_name, code_str);
834 return g_string_free (dbus_error_name, FALSE);
838 gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
839 DBusMessage *message,
848 error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
849 reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
854 if (error->domain == DBUS_GERROR)
855 reply = dbus_message_new_error (message,
856 dbus_g_error_get_name (error),
861 error_name = gerror_domaincode_to_dbus_error_name (object_info,
862 dbus_message_get_interface (message),
863 error->domain, error->code);
864 reply = dbus_message_new_error (message, error_name, error->message);
872 * The context of an asynchronous method call. See dbus_g_method_return() and
873 * dbus_g_method_return_error().
875 struct _DBusGMethodInvocation {
876 DBusGConnection *connection; /**< The connection */
877 DBusGMessage *message; /**< The message which generated the method call */
878 const DBusGObjectInfo *object; /**< The object the method was called on */
879 const DBusGMethodInfo *method; /**< The method called */
882 static DBusHandlerResult
883 invoke_object_method (GObject *object,
884 const DBusGObjectInfo *object_info,
885 const DBusGMethodInfo *method,
886 DBusConnection *connection,
887 DBusMessage *message)
889 gboolean had_error, call_only;
891 GValueArray *value_array;
892 GValue return_value = {0,};
895 GArray *out_param_values = NULL;
896 GValueArray *out_param_gvalues = NULL;
898 int out_param_pos, out_param_gvalue_pos;
899 DBusHandlerResult result;
901 gboolean have_retval;
902 gboolean retval_signals_error;
903 gboolean retval_is_synthetic;
904 gboolean retval_is_constant;
905 const char *arg_metadata;
909 /* Determine whether or not this method should be invoked in a new
912 if (strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0)
918 retval_signals_error = FALSE;
919 retval_is_synthetic = FALSE;
920 retval_is_constant = FALSE;
922 /* This is evil. We do this to work around the fact that
923 * the generated glib marshallers check a flag in the closure object
924 * which we don't care about. We don't need/want to create
925 * a new closure for each invocation.
927 memset (&closure, 0, sizeof (closure));
929 in_signature = method_input_signature_from_object_info (object_info, method);
931 /* Convert method IN parameters to GValueArray */
936 DBusGValueMarshalCtx context;
937 GError *error = NULL;
939 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
940 context.proxy = NULL;
942 types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
943 n_params = types_array->len;
944 types = (const GType*) types_array->data;
946 value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
947 if (value_array == NULL)
949 g_free (in_signature);
950 g_array_free (types_array, TRUE);
951 reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
952 dbus_connection_send (connection, reply, NULL);
953 dbus_message_unref (reply);
954 g_error_free (error);
955 return DBUS_HANDLER_RESULT_HANDLED;
957 g_array_free (types_array, TRUE);
960 /* Prepend object as first argument */
961 g_value_array_prepend (value_array, NULL);
962 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
963 g_value_set_object (g_value_array_get_nth (value_array, 0), object);
967 GValue context_value = {0,};
968 DBusGMethodInvocation *context;
969 context = g_new (DBusGMethodInvocation, 1);
970 context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
971 context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
972 context->object = object_info;
973 context->method = method;
974 g_value_init (&context_value, G_TYPE_POINTER);
975 g_value_set_pointer (&context_value, context);
976 g_value_array_append (value_array, &context_value);
985 arg_metadata = method_arg_info_from_object_info (object_info, method);
987 /* Count number of output parameters, and look for a return value */
989 while (*arg_metadata)
991 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
994 if (retval != RETVAL_NONE)
996 DBusSignatureIter tmp_sigiter;
997 /* This is the function return value */
998 g_assert (!have_retval);
1000 retval_is_synthetic = FALSE;
1005 g_assert_not_reached ();
1007 case RETVAL_NOERROR:
1008 retval_signals_error = FALSE;
1011 retval_signals_error = TRUE;
1015 retval_is_constant = arg_const;
1017 /* Initialize our return GValue with the specified type */
1018 dbus_signature_iter_init (&tmp_sigiter, argsig);
1019 g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
1023 /* It's a regular output value */
1028 /* For compatibility, if we haven't found a return value, we assume
1029 * the function returns a gboolean for signalling an error
1030 * (and therefore also takes a GError). We also note that it
1031 * is a "synthetic" return value; i.e. we aren't going to be
1032 * sending it over the bus, it's just to signal an error.
1037 retval_is_synthetic = TRUE;
1038 retval_signals_error = TRUE;
1039 g_value_init (&return_value, G_TYPE_BOOLEAN);
1042 /* Create an array to store the actual values of OUT parameters
1043 * (other than the real function return, if any). Then, create
1044 * a GValue boxed POINTER to each of those values, and append to
1045 * the invocation, so the method can return the OUT parameters.
1047 out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
1049 /* We have a special array of GValues for toplevel GValue return
1052 out_param_gvalues = g_value_array_new (out_param_count);
1054 out_param_gvalue_pos = 0;
1056 /* Reset argument metadata pointer */
1057 arg_metadata = method_arg_info_from_object_info (object_info, method);
1059 /* Iterate over output arguments again, this time allocating space for
1060 * them as appopriate.
1062 while (*arg_metadata)
1064 GValue value = {0, };
1065 GTypeCValue storage;
1066 DBusSignatureIter tmp_sigiter;
1067 GType current_gtype;
1069 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
1070 /* Skip over input arguments and the return value, if any */
1071 if (arg_in || retval != RETVAL_NONE)
1074 dbus_signature_iter_init (&tmp_sigiter, argsig);
1075 current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
1077 g_value_init (&value, G_TYPE_POINTER);
1079 /* We special case variants to make method invocation a bit nicer */
1080 if (current_gtype != G_TYPE_VALUE)
1082 memset (&storage, 0, sizeof (storage));
1083 g_array_append_val (out_param_values, storage);
1084 g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
1089 g_value_array_append (out_param_gvalues, NULL);
1090 g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
1091 out_param_gvalue_pos++;
1093 g_value_array_append (value_array, &value);
1097 /* Append GError as final argument if necessary */
1098 if (retval_signals_error)
1100 g_assert (have_retval);
1101 g_value_array_append (value_array, NULL);
1102 g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
1103 g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
1106 /* Actually invoke method */
1107 method->marshaller (&closure, have_retval ? &return_value : NULL,
1108 value_array->n_values,
1109 value_array->values,
1110 NULL, method->function);
1113 result = DBUS_HANDLER_RESULT_HANDLED;
1116 if (retval_signals_error)
1117 had_error = _dbus_gvalue_signals_error (&return_value);
1123 DBusMessageIter iter;
1125 reply = dbus_message_new_method_return (message);
1129 /* Append output arguments to reply */
1130 dbus_message_iter_init_append (reply, &iter);
1132 /* First, append the return value, unless it's synthetic */
1133 if (have_retval && !retval_is_synthetic)
1135 if (!_dbus_gvalue_marshal (&iter, &return_value))
1137 if (!retval_is_constant)
1138 g_value_unset (&return_value);
1141 /* Grab the argument metadata and iterate over it */
1142 arg_metadata = method_arg_info_from_object_info (object_info, method);
1144 /* Now append any remaining return values */
1146 out_param_gvalue_pos = 0;
1147 while (*arg_metadata)
1149 GValue gvalue = {0, };
1150 const char *arg_name;
1154 const char *arg_signature;
1155 DBusSignatureIter argsigiter;
1159 /* Iterate over only output values; skip over input
1160 arguments and the return value */
1161 arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
1163 while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
1165 /* If the last argument we saw was input or the return
1166 * value, we must be done iterating over output arguments.
1168 if (arg_in || retval != RETVAL_NONE)
1171 dbus_signature_iter_init (&argsigiter, arg_signature);
1173 g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
1174 if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
1176 if (!_dbus_gvalue_take (&gvalue,
1177 &(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
1178 g_assert_not_reached ();
1183 g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
1184 out_param_gvalue_pos++;
1187 if (!_dbus_gvalue_marshal (&iter, &gvalue))
1189 /* Here we actually free the allocated value; we
1190 * took ownership of it with _dbus_gvalue_take, unless
1191 * an annotation has specified this value as constant.
1194 g_value_unset (&gvalue);
1198 reply = gerror_to_dbus_error_message (object_info, message, gerror);
1202 dbus_connection_send (connection, reply, NULL);
1203 dbus_message_unref (reply);
1206 result = DBUS_HANDLER_RESULT_HANDLED;
1208 g_free (in_signature);
1211 g_array_free (out_param_values, TRUE);
1212 g_value_array_free (out_param_gvalues);
1214 g_value_array_free (value_array);
1217 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
1221 static DBusHandlerResult
1222 gobject_message_function (DBusConnection *connection,
1223 DBusMessage *message,
1231 const char *wincaps_propname;
1232 /* const char *wincaps_propiface; */
1233 DBusMessageIter iter;
1234 const DBusGMethodInfo *method;
1235 const DBusGObjectInfo *object_info;
1237 object = G_OBJECT (user_data);
1239 if (dbus_message_is_method_call (message,
1240 DBUS_INTERFACE_INTROSPECTABLE,
1242 return handle_introspect (connection, message, object);
1244 /* Try the metainfo, which lets us invoke methods */
1245 if (lookup_object_and_method (object, message, &object_info, &method))
1246 return invoke_object_method (object, object_info, method, connection, message);
1248 /* If no metainfo, we can still do properties and signals
1249 * via standard GLib introspection
1253 if (dbus_message_is_method_call (message,
1254 DBUS_INTERFACE_PROPERTIES,
1257 else if (dbus_message_is_method_call (message,
1258 DBUS_INTERFACE_PROPERTIES,
1262 if (!(setter || getter))
1263 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1265 dbus_message_iter_init (message, &iter);
1267 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
1269 g_warning ("Property get or set does not have an interface string as first arg\n");
1270 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1272 /* We never use the interface name; if we did, we'd need to
1273 * remember that it can be empty string for "pick one for me"
1275 /* dbus_message_iter_get_basic (&iter, &wincaps_propiface); */
1276 dbus_message_iter_next (&iter);
1278 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
1280 g_warning ("Property get or set does not have a property name string as second arg\n");
1281 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1283 dbus_message_iter_get_basic (&iter, &wincaps_propname);
1284 dbus_message_iter_next (&iter);
1286 s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
1288 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
1299 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
1301 g_warning ("Property set does not have a variant value as third arg\n");
1302 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1305 ret = set_object_property (connection, message, &iter,
1307 dbus_message_iter_next (&iter);
1311 ret = get_object_property (connection, message,
1316 g_assert_not_reached ();
1320 g_assert (ret != NULL);
1322 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
1323 g_warning ("Property get or set had too many arguments\n");
1325 dbus_connection_send (connection, ret, NULL);
1326 dbus_message_unref (ret);
1327 return DBUS_HANDLER_RESULT_HANDLED;
1330 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1333 static const DBusObjectPathVTable gobject_dbus_vtable = {
1334 gobject_unregister_function,
1335 gobject_message_function,
1341 DBusGConnection *connection;
1343 const char *signame;
1344 const char *sigiface;
1345 } DBusGSignalClosure;
1348 dbus_g_signal_closure_new (DBusGConnection *connection,
1350 const char *signame,
1351 const char *sigiface)
1353 DBusGSignalClosure *closure;
1355 closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
1357 closure->connection = dbus_g_connection_ref (connection);
1358 closure->object = object;
1359 closure->signame = signame;
1360 closure->sigiface = sigiface;
1361 return (GClosure*) closure;
1365 dbus_g_signal_closure_finalize (gpointer data,
1368 DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
1370 dbus_g_connection_unref (sigclosure->connection);
1374 signal_emitter_marshaller (GClosure *closure,
1376 guint n_param_values,
1377 const GValue *param_values,
1378 gpointer invocation_hint,
1379 gpointer marshal_data)
1381 DBusGSignalClosure *sigclosure;
1382 DBusMessage *signal;
1383 DBusMessageIter iter;
1387 sigclosure = (DBusGSignalClosure *) closure;
1389 g_assert (retval == NULL);
1391 path = _dbus_gobject_get_path (sigclosure->object);
1393 g_assert (path != NULL);
1395 signal = dbus_message_new_signal (path,
1396 sigclosure->sigiface,
1397 sigclosure->signame);
1400 g_error ("out of memory");
1404 dbus_message_iter_init_append (signal, &iter);
1406 /* First argument is the object itself, and we can't marshall that */
1407 for (i = 1; i < n_param_values; i++)
1409 if (!_dbus_gvalue_marshal (&iter,
1410 (GValue *) (&(param_values[i]))))
1412 g_warning ("failed to marshal parameter %d for signal %s",
1413 i, sigclosure->signame);
1417 dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
1420 dbus_message_unref (signal);
1424 export_signals (DBusGConnection *connection, const DBusGObjectInfo *info, GObject *object)
1427 const char *sigdata;
1429 const char *signame;
1431 gtype = G_TYPE_FROM_INSTANCE (object);
1433 sigdata = info->exported_signals;
1435 while (*sigdata != '\0')
1442 sigdata = propsig_iterate (sigdata, &iface, &signame);
1444 s = _dbus_gutils_wincaps_to_uscore (signame);
1446 id = g_signal_lookup (s, gtype);
1449 g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
1450 s, signame, g_type_name (gtype));
1455 g_signal_query (id, &query);
1457 if (query.return_type != G_TYPE_NONE)
1459 g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
1460 s, g_type_name (gtype), g_type_name (query.return_type));
1462 continue; /* FIXME: these could be listed as methods ? */
1465 closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
1466 g_closure_set_marshal (closure, signal_emitter_marshaller);
1468 g_signal_connect_closure_by_id (object,
1474 g_closure_add_finalize_notifier (closure, NULL,
1475 dbus_g_signal_closure_finalize);
1480 #include "dbus-glib-error-switch.h"
1483 dbus_set_g_error (GError **gerror,
1488 code = dbus_error_to_gerror_code (error->name);
1489 if (code != DBUS_GERROR_REMOTE_EXCEPTION)
1490 g_set_error (gerror, DBUS_GERROR,
1495 g_set_error (gerror, DBUS_GERROR,
1498 error->message ? error->message : "",
1504 dbus_g_error_info_free (gpointer p)
1506 DBusGErrorInfo *info;
1510 g_free (info->default_iface);
1514 /** @} */ /* end of internals */
1517 * @addtogroup DBusGLib
1522 * Install introspection information about the given object GType
1523 * sufficient to allow methods on the object to be invoked by name.
1524 * The introspection information is normally generated by
1525 * dbus-glib-tool, then this function is called in the
1526 * class_init() for the object class.
1528 * Once introspection information has been installed, instances of the
1529 * object registered with dbus_g_connection_register_g_object() can have
1530 * their methods invoked remotely.
1532 * @param object_type GType for the object
1533 * @param info introspection data generated by dbus-glib-tool
1536 dbus_g_object_type_install_info (GType object_type,
1537 const DBusGObjectInfo *info)
1539 g_return_if_fail (G_TYPE_IS_CLASSED (object_type));
1541 _dbus_g_value_types_init ();
1543 g_type_set_qdata (object_type,
1544 dbus_g_object_type_dbus_metadata_quark (),
1549 * Register a GError domain and set of codes with D-BUS. You must
1550 * have created a GEnum for the error codes. This function will not
1551 * be needed with an introspection-capable GLib.
1553 * @param domain the GError domain
1554 * @param default_iface the D-BUS interface used for error values by default, or #NULL
1555 * @param code_enum a GType for a GEnum of the error codes
1558 dbus_g_error_domain_register (GQuark domain,
1559 const char *default_iface,
1562 DBusGErrorInfo *info;
1564 g_return_if_fail (g_quark_to_string (domain) != NULL);
1565 g_return_if_fail (code_enum != G_TYPE_INVALID);
1566 g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
1568 g_static_rw_lock_writer_lock (&globals_lock);
1570 if (error_metadata == NULL)
1571 g_datalist_init (&error_metadata);
1573 info = g_datalist_id_get_data (&error_metadata, domain);
1577 g_warning ("Metadata for error domain \"%s\" already registered\n",
1578 g_quark_to_string (domain));
1582 info = g_new0 (DBusGErrorInfo, 1);
1583 info->default_iface = g_strdup (default_iface);
1584 info->code_enum = code_enum;
1586 g_datalist_id_set_data_full (&error_metadata,
1589 dbus_g_error_info_free);
1592 g_static_rw_lock_writer_unlock (&globals_lock);
1596 unregister_gobject (DBusGConnection *connection, GObject *dead)
1599 path = g_object_steal_data (dead, "dbus_glib_object_path");
1600 dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection), path);
1605 * Registers a GObject at the given path. Properties, methods, and signals
1606 * of the object can then be accessed remotely. Methods are only available
1607 * if method introspection data has been added to the object's class
1608 * with g_object_class_install_info().
1610 * The registration will be cancelled if either the DBusConnection or
1611 * the GObject gets finalized.
1613 * @param connection the D-BUS connection
1614 * @param at_path the path where the object will live (the object's name)
1615 * @param object the object
1618 dbus_g_connection_register_g_object (DBusGConnection *connection,
1619 const char *at_path,
1622 const DBusGObjectInfo *info;
1623 g_return_if_fail (connection != NULL);
1624 g_return_if_fail (at_path != NULL);
1625 g_return_if_fail (G_IS_OBJECT (object));
1627 info = lookup_object_info (object);
1630 g_warning ("No introspection data registered for object class \"%s\"",
1631 g_type_name (G_TYPE_FROM_INSTANCE (object)));
1635 if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
1637 &gobject_dbus_vtable,
1640 g_error ("Failed to register GObject with DBusConnection");
1644 export_signals (connection, info, object);
1646 g_object_set_data (object, "dbus_glib_object_path", g_strdup (at_path));
1647 g_object_weak_ref (object, (GWeakNotify)unregister_gobject, connection);
1651 dbus_g_connection_lookup_g_object (DBusGConnection *connection,
1652 const char *at_path)
1655 if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &ret))
1664 } DBusGFuncSignature;
1667 funcsig_hash (gconstpointer key)
1669 const DBusGFuncSignature *sig = key;
1675 types = sig->params;
1677 for (i = 0; i < sig->n_params; i++)
1679 ret += (int) (*types);
1687 funcsig_equal (gconstpointer aval,
1690 const DBusGFuncSignature *a = aval;
1691 const DBusGFuncSignature *b = bval;
1692 const GType *atypes;
1693 const GType *btypes;
1696 if (a->rettype != b->rettype
1697 || a->n_params != b->n_params)
1703 for (i = 0; i < a->n_params; i++)
1705 if (*btypes != *atypes)
1715 _dbus_gobject_lookup_marshaller (GType rettype,
1717 const GType *param_types)
1719 GClosureMarshal ret;
1720 DBusGFuncSignature sig;
1724 /* Convert to fundamental types */
1725 rettype = G_TYPE_FUNDAMENTAL (rettype);
1726 params = g_new (GType, n_params);
1727 for (i = 0; i < n_params; i++)
1728 params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
1730 sig.rettype = rettype;
1731 sig.n_params = n_params;
1732 sig.params = params;
1734 g_static_rw_lock_reader_lock (&globals_lock);
1737 ret = g_hash_table_lookup (marshal_table, &sig);
1741 g_static_rw_lock_reader_unlock (&globals_lock);
1745 if (rettype == G_TYPE_NONE)
1748 ret = g_cclosure_marshal_VOID__VOID;
1749 else if (n_params == 1)
1753 case G_TYPE_BOOLEAN:
1754 ret = g_cclosure_marshal_VOID__BOOLEAN;
1757 ret = g_cclosure_marshal_VOID__UCHAR;
1760 ret = g_cclosure_marshal_VOID__INT;
1763 ret = g_cclosure_marshal_VOID__UINT;
1766 ret = g_cclosure_marshal_VOID__DOUBLE;
1769 ret = g_cclosure_marshal_VOID__STRING;
1772 ret = g_cclosure_marshal_VOID__BOXED;
1776 else if (n_params == 3
1777 && params[0] == G_TYPE_STRING
1778 && params[1] == G_TYPE_STRING
1779 && params[2] == G_TYPE_STRING)
1781 ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
1791 * Register a GClosureMarshal to be used for signal invocations,
1792 * giving its return type and a list of parameter types,
1793 * followed by G_TYPE_INVALID.
1795 * This function will not be needed once GLib includes libffi.
1797 * @param marshaller a GClosureMarshal to be used for invocation
1798 * @param rettype a GType for the return type of the function
1799 * @param ... The parameter GTypes, followed by G_TYPE_INVALID
1802 dbus_g_object_register_marshaller (GClosureMarshal marshaller,
1810 va_start (args, rettype);
1812 types = g_array_new (TRUE, TRUE, sizeof (GType));
1814 while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
1815 g_array_append_val (types, gtype);
1817 dbus_g_object_register_marshaller_array (marshaller, rettype,
1818 types->len, (GType*) types->data);
1820 g_array_free (types, TRUE);
1825 * Register a GClosureMarshal to be used for signal invocations.
1826 * See also #dbus_g_object_register_marshaller
1828 * @param marshaller a GClosureMarshal to be used for invocation
1829 * @param rettype a GType for the return type of the function
1830 * @param n_types number of function parameters
1831 * @param types a C array of GTypes values
1834 dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
1839 DBusGFuncSignature *sig;
1842 g_static_rw_lock_writer_lock (&globals_lock);
1844 if (marshal_table == NULL)
1845 marshal_table = g_hash_table_new_full (funcsig_hash,
1849 sig = g_new0 (DBusGFuncSignature, 1);
1850 sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
1851 sig->n_params = n_types;
1852 sig->params = g_new (GType, n_types);
1853 for (i = 0; i < n_types; i++)
1854 sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
1856 g_hash_table_insert (marshal_table, sig, marshaller);
1858 g_static_rw_lock_writer_unlock (&globals_lock);
1863 * Get the reply message to append reply values
1864 * Used as a sidedoor when you can't generate dbus values
1865 * of the correct type due to glib binding limitations
1867 * @param context the method context
1870 dbus_g_method_return_get_reply (DBusGMethodInvocation *context)
1872 return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
1876 * Send a manually created reply message
1877 * Used as a sidedoor when you can't generate dbus values
1878 * of the correct type due to glib binding limitations
1880 * @param context the method context
1881 * @param reply the reply message, will be unreffed
1884 dbus_g_method_return_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
1886 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
1887 dbus_message_unref (reply);
1889 dbus_g_connection_unref (context->connection);
1890 dbus_g_message_unref (context->message);
1896 * Send a return message for a given method invocation, with arguments.
1897 * This function also frees the sending context.
1899 * @param context the method context
1902 dbus_g_method_return (DBusGMethodInvocation *context, ...)
1905 DBusMessageIter iter;
1911 reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
1912 out_sig = method_output_signature_from_object_info (context->object, context->method);
1913 argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
1915 dbus_message_iter_init_append (reply, &iter);
1917 va_start (args, context);
1918 for (i = 0; i < argsig->len; i++)
1920 GValue value = {0,};
1922 g_value_init (&value, g_array_index (argsig, GType, i));
1924 G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
1930 _dbus_gvalue_marshal (&iter, &value);
1934 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
1935 dbus_message_unref (reply);
1937 dbus_g_connection_unref (context->connection);
1938 dbus_g_message_unref (context->message);
1944 * Send a error message for a given method invocation.
1945 * This function also frees the sending context.
1947 * @param context the method context
1948 * @param error the error to send.
1951 dbus_g_method_return_error (DBusGMethodInvocation *context, GError *error)
1954 reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
1955 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
1956 dbus_message_unref (reply);
1960 /** @} */ /* end of public API */
1962 const char * _dbus_gobject_get_path (GObject *obj)
1964 return g_object_get_data (obj, "dbus_glib_object_path");
1967 #ifdef DBUS_BUILD_TESTS
1971 _dummy_function (void)
1975 /* Data structures copied from one generated by current dbus-binding-tool;
1976 * we need to support this layout forever
1978 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
1979 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
1980 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
1981 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
1982 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
1983 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
1984 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
1985 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
1986 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
1987 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
1988 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
1989 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
1990 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
1991 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
1992 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
1993 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
1994 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
1995 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
1996 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
1997 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
1998 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
1999 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
2000 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
2001 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
2002 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
2003 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
2004 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
2005 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
2006 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
2007 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
2008 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
2011 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
2013 dbus_glib_internal_test_methods,
2015 "org.freedesktop.DBus.Tests.MyObject\0DoNothing\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Increment\0S\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetval\0S\0x\0I\0u\0arg1\0O\0F\0R\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetvalError\0S\0x\0I\0u\0arg1\0O\0F\0E\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ThrowError\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Uppercase\0S\0arg0\0I\0s\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyArgs\0S\0x\0I\0u\0str\0I\0s\0trouble\0I\0d\0d_ret\0O\0F\0N\0d\0str_ret\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyReturn\0S\0arg0\0O\0F\0N\0u\0arg1\0O\0F\0N\0s\0arg2\0O\0F\0N\0i\0arg3\0O\0F\0N\0u\0arg4\0O\0F\0N\0u\0arg5\0O\0C\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Stringify\0S\0val\0I\0v\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Unstringify\0S\0val\0I\0s\0arg1\0O\0F\0N\0v\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive1\0S\0arg0\0I\0au\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive2\0S\0arg0\0I\0u\0arg1\0O\0F\0N\0au\0\0org.freedesktop.DBus.Tests.MyObject\0ManyUppercase\0S\0arg0\0I\0as\0arg1\0O\0F\0N\0as\0\0org.freedesktop.DBus.Tests.MyObject\0StrHashLen\0S\0arg0\0I\0a{ss}\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0SendCar\0S\0arg0\0I\0(suv)\0arg1\0O\0F\0N\0(uo)\0\0org.freedesktop.DBus.Tests.MyObject\0GetHash\0S\0arg0\0O\0F\0N\0a{ss}\0\0org.freedesktop.DBus.Tests.MyObject\0RecArrays\0S\0val\0I\0aas\0arg1\0O\0F\0N\0aau\0\0org.freedesktop.DBus.Tests.MyObject\0Objpath\0S\0arg0\0I\0o\0arg1\0O\0C\0N\0o\0\0org.freedesktop.DBus.Tests.MyObject\0GetObjs\0S\0arg0\0O\0F\0N\0ao\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementVal\0S\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncIncrement\0A\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncThrowError\0A\0\0org.freedesktop.DBus.Tests.MyObject\0GetVal\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ManyStringify\0S\0arg0\0I\0a{sv}\0arg1\0O\0F\0N\0a{sv}\0\0org.freedesktop.DBus.Tests.MyObject\0EmitFrobnicate\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Terminate\0S\0\0org.freedesktop.DBus.Tests.FooObject\0GetValue\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignals\0S\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignal2\0S\0\0org.freedesktop.DBus.Tests.FooObject\0Terminate\0S\0\0\0",
2016 "org.freedesktop.DBus.Tests.MyObject\0Frobnicate\0org.freedesktop.DBus.Tests.FooObject\0Sig0\0org.freedesktop.DBus.Tests.FooObject\0Sig1\0org.freedesktop.DBus.Tests.FooObject\0Sig2\0\0",
2022 * @ingroup DBusGLibInternals
2023 * Unit test for GLib GObject integration ("skeletons")
2024 * @returns #TRUE on success.
2027 _dbus_gobject_test (const char *test_data_dir)
2031 const char *arg_name;
2035 const char *arg_signature;
2036 const char *sigdata;
2038 const char *signame;
2040 static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
2041 { "SetFoo", "set_foo" },
2043 { "GetFooBar", "get_foo_bar" },
2044 { "Hello", "hello" }
2046 /* Impossible-to-handle cases */
2047 /* { "FrobateUIHandler", "frobate_ui_handler" } */
2050 /* Test lookup in our hardcoded object info; if these tests fail
2051 * then it likely means you changed the generated object info in an
2052 * incompatible way and broke the lookup functions. In that case
2053 * you need to bump the version and use a new structure instead. */
2055 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
2056 &(dbus_glib_internal_test_methods[0]));
2057 g_assert (*arg == '\0');
2060 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
2061 &(dbus_glib_internal_test_methods[1]));
2062 g_assert (*arg != '\0');
2063 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2064 g_assert (!strcmp (arg_name, "x"));
2065 g_assert (arg_in == TRUE);
2066 g_assert (!strcmp (arg_signature, "u"));
2067 g_assert (*arg != '\0');
2068 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2069 g_assert (arg_in == FALSE);
2070 g_assert (retval == RETVAL_NONE);
2071 g_assert (!strcmp (arg_signature, "u"));
2072 g_assert (*arg == '\0');
2074 /* IncrementRetval */
2075 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
2076 &(dbus_glib_internal_test_methods[2]));
2077 g_assert (*arg != '\0');
2078 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2079 g_assert (!strcmp (arg_name, "x"));
2080 g_assert (arg_in == TRUE);
2081 g_assert (!strcmp (arg_signature, "u"));
2082 g_assert (*arg != '\0');
2083 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2084 g_assert (retval == RETVAL_NOERROR);
2085 g_assert (arg_in == FALSE);
2086 g_assert (!strcmp (arg_signature, "u"));
2087 g_assert (*arg == '\0');
2089 /* IncrementRetvalError */
2090 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
2091 &(dbus_glib_internal_test_methods[3]));
2092 g_assert (*arg != '\0');
2093 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2094 g_assert (!strcmp (arg_name, "x"));
2095 g_assert (arg_in == TRUE);
2096 g_assert (!strcmp (arg_signature, "u"));
2097 g_assert (*arg != '\0');
2098 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2099 g_assert (retval == RETVAL_ERROR);
2100 g_assert (arg_in == FALSE);
2101 g_assert (!strcmp (arg_signature, "u"));
2102 g_assert (*arg == '\0');
2105 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
2106 &(dbus_glib_internal_test_methods[8]));
2107 g_assert (*arg != '\0');
2108 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2109 g_assert (!strcmp (arg_name, "val"));
2110 g_assert (arg_in == TRUE);
2111 g_assert (!strcmp (arg_signature, "v"));
2112 g_assert (*arg != '\0');
2113 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
2114 g_assert (retval == RETVAL_NONE);
2115 g_assert (arg_in == FALSE);
2116 g_assert (!strcmp (arg_signature, "s"));
2117 g_assert (*arg == '\0');
2119 sigdata = dbus_glib_internal_test_object_info.exported_signals;
2120 g_assert (*sigdata != '\0');
2121 sigdata = propsig_iterate (sigdata, &iface, &signame);
2122 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
2123 g_assert (!strcmp (signame, "Frobnicate"));
2124 g_assert (*sigdata != '\0');
2125 sigdata = propsig_iterate (sigdata, &iface, &signame);
2126 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
2127 g_assert (!strcmp (signame, "Sig0"));
2128 g_assert (*sigdata != '\0');
2129 sigdata = propsig_iterate (sigdata, &iface, &signame);
2130 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
2131 g_assert (!strcmp (signame, "Sig1"));
2132 g_assert (*sigdata != '\0');
2133 sigdata = propsig_iterate (sigdata, &iface, &signame);
2134 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
2135 g_assert (!strcmp (signame, "Sig2"));
2136 g_assert (*sigdata == '\0');
2140 while (i < (int) G_N_ELEMENTS (name_pairs))
2145 uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
2146 wincaps = uscore_to_wincaps (name_pairs[i].uscore);
2148 if (strcmp (uscore, name_pairs[i].uscore) != 0)
2150 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
2151 name_pairs[i].wincaps, name_pairs[i].uscore,
2156 if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
2158 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
2159 name_pairs[i].uscore, name_pairs[i].wincaps,
2173 #endif /* DBUS_BUILD_TESTS */