#include "dbus-gtest.h"
#include "dbus-gutils.h"
#include "dbus-gobject.h"
+#include "dbus-gsignature.h"
#include "dbus-gvalue.h"
#include "dbus-gmarshal.h"
#include "dbus-gvalue-utils.h"
* @{
*/
+typedef struct
+{
+ char *default_iface;
+ GType code_enum;
+} DBusGErrorInfo;
+
static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
-static GHashTable *info_hash = NULL;
static GHashTable *marshal_table = NULL;
+static GData *error_metadata = NULL;
static char*
uscore_to_wincaps (const char *uscore)
return string_table_lookup (get_method_data (object, method), 3);/*RB was 2*/
}
+typedef enum
+{
+ RETVAL_NONE,
+ RETVAL_NOERROR,
+ RETVAL_ERROR
+} RetvalType;
+
static const char *
-arg_iterate (const char *data, const char **name, gboolean *in,
- const char **type)
+arg_iterate (const char *data,
+ const char **name,
+ gboolean *in,
+ gboolean *constval,
+ RetvalType *retval,
+ const char **type)
{
- *name = data;
+ gboolean inarg;
+
+ if (name)
+ *name = data;
data = string_table_next (data);
switch (*data)
{
case 'I':
- *in = TRUE;
+ inarg = TRUE;
break;
case 'O':
- *in = FALSE;
+ inarg = FALSE;
break;
default:
- g_warning ("invalid arg direction");
+ g_warning ("invalid arg direction '%c'", *data);
+ inarg = FALSE;
break;
}
+ if (in)
+ *in = inarg;
+
+ if (!inarg)
+ {
+ data = string_table_next (data);
+ switch (*data)
+ {
+ case 'F':
+ if (constval)
+ *constval = FALSE;
+ break;
+ case 'C':
+ if (constval)
+ *constval = TRUE;
+ break;
+ default:
+ g_warning ("invalid arg const value '%c'", *data);
+ break;
+ }
+ data = string_table_next (data);
+ switch (*data)
+ {
+ case 'N':
+ if (retval)
+ *retval = RETVAL_NONE;
+ break;
+ case 'E':
+ if (retval)
+ *retval = RETVAL_ERROR;
+ break;
+ case 'R':
+ if (retval)
+ *retval = RETVAL_NOERROR;
+ break;
+ default:
+ g_warning ("invalid arg ret value '%c'", *data);
+ break;
+ }
+ }
+ else
+ {
+ if (constval)
+ *constval = FALSE;
+ if (retval)
+ *retval = FALSE;
+ }
data = string_table_next (data);
- *type = data;
+ if (type)
+ *type = data;
return string_table_next (data);
}
gboolean arg_in;
const char *type;
- arg = arg_iterate (arg, &name, &arg_in, &type);
+ arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
if (arg_in == in)
g_string_append (ret, type);
return string_table_next (data);
}
+static GQuark
+dbus_g_object_type_dbus_metadata_quark (void)
+{
+ static GQuark quark;
+
+ if (!quark)
+ quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
+ return quark;
+}
+
static const DBusGObjectInfo *
lookup_object_info (GObject *object)
{
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));
+ info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
- if (info != NULL && info->format_version == 0)
+ if (info != NULL && info->format_version >= 0)
{
ret = info;
break;
}
}
- out:
- g_static_rw_lock_reader_unlock (&globals_lock);
-
return ret;
}
for (; methods; methods = methods->next)
{
DBusGMethodInfo *method;
- method = methods->data;
const char *args;
+ method = methods->data;
g_string_append_printf (xml, " <method name=\"%s\">\n",
method_name_from_object_info (object_info, method));
gboolean arg_in;
const char *type;
- args = arg_iterate (args, &name, &arg_in, &type);
+ args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
/* FIXME - handle container types */
g_string_append_printf (xml, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
for (arg = 0; arg < query.n_params; arg++)
{
- const char *dbus_type = dbus_gtype_to_signature (query.param_types[arg]);
+ 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_free (dbus_type);
}
g_string_append (xml, " </signal>\n");
{
const char *propname;
GParamSpec *spec;
- const char *dbus_type;
+ char *dbus_type;
gboolean can_set;
gboolean can_get;
char *s;
propname = properties->data;
+ spec = NULL;
s = _dbus_gutils_wincaps_to_uscore (spec->name);
g_assert (spec != NULL);
g_free (s);
- dbus_type = dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
+ 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 &&
g_string_append (xml, "\"/>\n");
}
+ g_free (dbus_type);
g_free (s);
g_string_append (xml, " </property>\n");
context.proxy = NULL;
g_value_init (&value, pspec->value_type);
- if (dbus_gvalue_demarshal (&context, &sub, &value, NULL))
+ if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
{
g_object_set_property (object,
pspec->name,
dbus_message_iter_init_append (message, &iter);
- if (!dbus_gvalue_marshal (&iter, &value))
+ if (!_dbus_gvalue_marshal (&iter, &value))
{
dbus_message_unref (ret);
ret = dbus_message_new_error (message,
static char *
gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
+ const char *msg_interface,
GQuark domain, gint code)
{
const char *domain_str;
if (!domain_str || !code_str)
{
+ DBusGErrorInfo *info;
+
+ g_static_rw_lock_reader_lock (&globals_lock);
+
+ if (error_metadata != NULL)
+ info = g_datalist_id_get_data (&error_metadata, domain);
+ else
+ info = NULL;
+
+ g_static_rw_lock_reader_unlock (&globals_lock);
+
+ if (info)
+ {
+ GEnumValue *value;
+ GEnumClass *klass;
+
+ klass = g_type_class_ref (info->code_enum);
+ value = g_enum_get_value (klass, code);
+ g_type_class_unref (klass);
+
+ domain_str = info->default_iface;
+ code_str = value->value_nick;
+ }
+ }
+
+ if (!domain_str)
+ domain_str = msg_interface;
+
+ if (!domain_str || !code_str)
+ {
/* If we can't map it sensibly, make up an error name */
char *domain_from_quark;
else
{
char *error_name;
- error_name = gerror_domaincode_to_dbus_error_name (object_info, error->domain, error->code);
+ error_name = gerror_domaincode_to_dbus_error_name (object_info,
+ dbus_message_get_interface (message),
+ error->domain, error->code);
reply = dbus_message_new_error (message, error_name, error->message);
g_free (error_name);
}
gboolean had_error, call_only;
GError *gerror;
GValueArray *value_array;
- GValue object_value = {0,};
- GValue error_value = {0,};
GValue return_value = {0,};
GClosure closure;
char *in_signature;
- char *out_signature = NULL;
- int current_type;
- DBusSignatureIter out_signature_iter;
GArray *out_param_values = NULL;
GValueArray *out_param_gvalues = NULL;
int out_param_count;
int out_param_pos, out_param_gvalue_pos;
DBusHandlerResult result;
DBusMessage *reply;
+ gboolean have_retval;
+ gboolean retval_signals_error;
+ gboolean retval_is_synthetic;
+ gboolean retval_is_constant;
+ const char *arg_metadata;
gerror = NULL;
+ /* Determine whether or not this method should be invoked in a new
+ thread
+ */
if (strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0)
call_only = TRUE;
else
call_only = FALSE;
+ have_retval = FALSE;
+ retval_signals_error = FALSE;
+ retval_is_synthetic = FALSE;
+ retval_is_constant = FALSE;
+
/* This is evil. We do this to work around the fact that
* the generated glib marshallers check a flag in the closure object
* which we don't care about. We don't need/want to create
context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
context.proxy = NULL;
- types_array = dbus_gtypes_from_arg_signature (in_signature, FALSE);
+ types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
n_params = types_array->len;
types = (const GType*) types_array->data;
- value_array = dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
+ value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
if (value_array == NULL)
{
g_free (in_signature);
}
/* Prepend object as first argument */
- g_value_init (&object_value, G_TYPE_OBJECT);
- g_value_set_object (&object_value, object);
- g_value_array_prepend (value_array, &object_value);
-
+ g_value_array_prepend (value_array, NULL);
+ g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
+ g_value_set_object (g_value_array_get_nth (value_array, 0), object);
+
if (call_only)
{
GValue context_value = {0,};
}
else
{
- out_signature = method_output_signature_from_object_info (object_info, method);
+ RetvalType retval;
+ gboolean arg_in;
+ gboolean arg_const;
+ const char *argsig;
- /* Count number of output parameters */
- dbus_signature_iter_init (&out_signature_iter, out_signature);
+ arg_metadata = method_arg_info_from_object_info (object_info, method);
+
+ /* Count number of output parameters, and look for a return value */
out_param_count = 0;
- while ((current_type = dbus_signature_iter_get_current_type (&out_signature_iter)) != DBUS_TYPE_INVALID)
+ while (*arg_metadata)
+ {
+ arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
+ if (arg_in)
+ continue;
+ if (retval != RETVAL_NONE)
+ {
+ DBusSignatureIter tmp_sigiter;
+ /* This is the function return value */
+ g_assert (!have_retval);
+ have_retval = TRUE;
+ retval_is_synthetic = FALSE;
+
+ switch (retval)
+ {
+ case RETVAL_NONE:
+ g_assert_not_reached ();
+ break;
+ case RETVAL_NOERROR:
+ retval_signals_error = FALSE;
+ break;
+ case RETVAL_ERROR:
+ retval_signals_error = TRUE;
+ break;
+ }
+
+ retval_is_constant = arg_const;
+
+ /* Initialize our return GValue with the specified type */
+ dbus_signature_iter_init (&tmp_sigiter, argsig);
+ g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
+ }
+ else
+ {
+ /* It's a regular output value */
+ out_param_count++;
+ }
+ }
+
+ /* For compatibility, if we haven't found a return value, we assume
+ * the function returns a gboolean for signalling an error
+ * (and therefore also takes a GError). We also note that it
+ * is a "synthetic" return value; i.e. we aren't going to be
+ * sending it over the bus, it's just to signal an error.
+ */
+ if (!have_retval)
{
- out_param_count++;
- dbus_signature_iter_next (&out_signature_iter);
+ have_retval = TRUE;
+ retval_is_synthetic = TRUE;
+ retval_signals_error = TRUE;
+ g_value_init (&return_value, G_TYPE_BOOLEAN);
}
- /* Create an array to store the actual values of OUT
- * parameters. Then, create a GValue boxed POINTER
- * to each of those values, and append to the invocation,
- * so the method can return the OUT parameters.
+ /* Create an array to store the actual values of OUT parameters
+ * (other than the real function return, if any). Then, create
+ * a GValue boxed POINTER to each of those values, and append to
+ * the invocation, so the method can return the OUT parameters.
*/
out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
out_param_gvalues = g_value_array_new (out_param_count);
out_param_pos = 0;
out_param_gvalue_pos = 0;
- dbus_signature_iter_init (&out_signature_iter, out_signature);
- while ((current_type = dbus_signature_iter_get_current_type (&out_signature_iter)) != DBUS_TYPE_INVALID)
+
+ /* Reset argument metadata pointer */
+ arg_metadata = method_arg_info_from_object_info (object_info, method);
+
+ /* Iterate over output arguments again, this time allocating space for
+ * them as appopriate.
+ */
+ while (*arg_metadata)
{
GValue value = {0, };
GTypeCValue storage;
+ DBusSignatureIter tmp_sigiter;
+ GType current_gtype;
+
+ arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
+ /* Skip over input arguments and the return value, if any */
+ if (arg_in || retval != RETVAL_NONE)
+ continue;
+
+ dbus_signature_iter_init (&tmp_sigiter, argsig);
+ current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
g_value_init (&value, G_TYPE_POINTER);
/* We special case variants to make method invocation a bit nicer */
- if (current_type != DBUS_TYPE_VARIANT)
+ if (current_gtype != G_TYPE_VALUE)
{
memset (&storage, 0, sizeof (storage));
g_array_append_val (out_param_values, storage);
out_param_gvalue_pos++;
}
g_value_array_append (value_array, &value);
- dbus_signature_iter_next (&out_signature_iter);
}
+ }
- /* Append GError as final argument */
- g_value_init (&error_value, G_TYPE_POINTER);
- g_value_set_pointer (&error_value, &gerror);
- g_value_array_append (value_array, &error_value);
+ /* Append GError as final argument if necessary */
+ if (retval_signals_error)
+ {
+ g_assert (have_retval);
+ g_value_array_append (value_array, NULL);
+ g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
+ g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
}
+
/* Actually invoke method */
- g_value_init (&return_value, G_TYPE_BOOLEAN);
- method->marshaller (&closure, &return_value,
+ method->marshaller (&closure, have_retval ? &return_value : NULL,
value_array->n_values,
value_array->values,
NULL, method->function);
result = DBUS_HANDLER_RESULT_HANDLED;
goto done;
}
- had_error = !g_value_get_boolean (&return_value);
+ if (retval_signals_error)
+ had_error = _dbus_gvalue_signals_error (&return_value);
+ else
+ had_error = FALSE;
if (!had_error)
{
if (reply == NULL)
goto nomem;
- /* Append OUT arguments to reply */
+ /* Append output arguments to reply */
dbus_message_iter_init_append (reply, &iter);
- dbus_signature_iter_init (&out_signature_iter, out_signature);
+
+ /* First, append the return value, unless it's synthetic */
+ if (have_retval && !retval_is_synthetic)
+ {
+ if (!_dbus_gvalue_marshal (&iter, &return_value))
+ goto nomem;
+ if (!retval_is_constant)
+ g_value_unset (&return_value);
+ }
+
+ /* Grab the argument metadata and iterate over it */
+ arg_metadata = method_arg_info_from_object_info (object_info, method);
+
+ /* Now append any remaining return values */
out_param_pos = 0;
out_param_gvalue_pos = 0;
- while ((current_type = dbus_signature_iter_get_current_type (&out_signature_iter)) != DBUS_TYPE_INVALID)
+ while (*arg_metadata)
{
GValue gvalue = {0, };
+ const char *arg_name;
+ gboolean arg_in;
+ gboolean constval;
+ RetvalType retval;
+ const char *arg_signature;
+ DBusSignatureIter argsigiter;
+
+ do
+ {
+ /* Iterate over only output values; skip over input
+ arguments and the return value */
+ arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ }
+ while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
+
+ /* If the last argument we saw was input or the return
+ * value, we must be done iterating over output arguments.
+ */
+ if (arg_in || retval != RETVAL_NONE)
+ break;
+
+ dbus_signature_iter_init (&argsigiter, arg_signature);
- g_value_init (&gvalue, dbus_gtype_from_signature_iter (&out_signature_iter, FALSE));
- if (current_type != DBUS_TYPE_VARIANT)
+ g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
+ if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
{
- if (!dbus_gvalue_take (&gvalue,
+ if (!_dbus_gvalue_take (&gvalue,
&(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
g_assert_not_reached ();
out_param_pos++;
out_param_gvalue_pos++;
}
- if (!dbus_gvalue_marshal (&iter, &gvalue))
+ if (!_dbus_gvalue_marshal (&iter, &gvalue))
goto nomem;
/* Here we actually free the allocated value; we
- * took ownership of it with dbus_gvalue_take.
+ * took ownership of it with _dbus_gvalue_take, unless
+ * an annotation has specified this value as constant.
*/
- g_value_unset (&gvalue);
- dbus_signature_iter_next (&out_signature_iter);
+ if (!constval)
+ g_value_unset (&gvalue);
}
}
else
result = DBUS_HANDLER_RESULT_HANDLED;
done:
g_free (in_signature);
- g_free (out_signature);
if (!call_only)
{
g_array_free (out_param_values, TRUE);
g_value_array_free (out_param_gvalues);
- g_value_unset (&object_value);
- g_value_unset (&error_value);
}
g_value_array_free (value_array);
- g_value_unset (&return_value);
return result;
nomem:
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-static DBusObjectPathVTable gobject_dbus_vtable = {
+static const DBusObjectPathVTable gobject_dbus_vtable = {
gobject_unregister_function,
gobject_message_function,
NULL
/* First argument is the object itself, and we can't marshall that */
for (i = 1; i < n_param_values; i++)
{
- if (!dbus_gvalue_marshal (&iter,
+ if (!_dbus_gvalue_marshal (&iter,
(GValue *) (&(param_values[i]))))
{
g_warning ("failed to marshal parameter %d for signal %s",
}
}
+#include "dbus-glib-error-switch.h"
+
+void
+dbus_set_g_error (GError **gerror,
+ DBusError *error)
+{
+ int code;
+
+ code = dbus_error_to_gerror_code (error->name);
+ if (code != DBUS_GERROR_REMOTE_EXCEPTION)
+ g_set_error (gerror, DBUS_GERROR,
+ code,
+ "%s",
+ error->message);
+ else
+ g_set_error (gerror, DBUS_GERROR,
+ code,
+ "%s%c%s",
+ error->message ? error->message : "",
+ '\0',
+ error->name);
+}
+
+static void
+dbus_g_error_info_free (gpointer p)
+{
+ DBusGErrorInfo *info;
+
+ info = p;
+
+ g_free (info->default_iface);
+ g_free (info);
+}
+
/** @} */ /* end of internals */
/**
dbus_g_object_type_install_info (GType object_type,
const DBusGObjectInfo *info)
{
- GObjectClass *object_class;
-
- g_return_if_fail (G_TYPE_IS_OBJECT (object_type));
+ g_return_if_fail (G_TYPE_IS_CLASSED (object_type));
- dbus_g_value_types_init ();
+ _dbus_g_value_types_init ();
- object_class = g_type_class_peek (object_type);
+ g_type_set_qdata (object_type,
+ dbus_g_object_type_dbus_metadata_quark (),
+ (gpointer) info);
+}
- g_return_if_fail (G_IS_OBJECT_CLASS (object_class));
+/**
+ * Register a GError domain and set of codes with D-BUS. You must
+ * have created a GEnum for the error codes. This function will not
+ * be needed with an introspection-capable GLib.
+ *
+ * @param domain the GError domain
+ * @param default_iface the D-BUS interface used for error values by default, or #NULL
+ * @param code_enum a GType for a GEnum of the error codes
+ */
+void
+dbus_g_error_domain_register (GQuark domain,
+ const char *default_iface,
+ GType code_enum)
+{
+ DBusGErrorInfo *info;
+
+ g_return_if_fail (g_quark_to_string (domain) != NULL);
+ g_return_if_fail (code_enum != G_TYPE_INVALID);
+ g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
g_static_rw_lock_writer_lock (&globals_lock);
- if (info_hash == NULL)
+ if (error_metadata == NULL)
+ g_datalist_init (&error_metadata);
+
+ info = g_datalist_id_get_data (&error_metadata, domain);
+
+ if (info != NULL)
{
- info_hash = g_hash_table_new (NULL, NULL); /* direct hash */
+ g_warning ("Metadata for error domain \"%s\" already registered\n",
+ g_quark_to_string (domain));
+ }
+ else
+ {
+ info = g_new0 (DBusGErrorInfo, 1);
+ info->default_iface = g_strdup (default_iface);
+ info->code_enum = code_enum;
+
+ g_datalist_id_set_data_full (&error_metadata,
+ domain,
+ info,
+ dbus_g_error_info_free);
}
-
- g_hash_table_replace (info_hash, object_class, (void*) info);
g_static_rw_lock_writer_unlock (&globals_lock);
}
break;
}
}
- }
- else if (n_params == 3
- && params[0] == G_TYPE_STRING
- && params[1] == G_TYPE_STRING
- && params[2] == G_TYPE_STRING)
- {
- ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
+ else if (n_params == 3
+ && params[0] == G_TYPE_STRING
+ && params[1] == G_TYPE_STRING
+ && params[2] == G_TYPE_STRING)
+ {
+ ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
+ }
}
}
* @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 types a C array of GTypes values
*/
void
dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
}
/**
+ * Get the sender of a message so we can send a
+ * "reply" later (i.e. send a message directly
+ * to a service which invoked the method at a
+ * later time).
+ *
+ * @param context the method context
+ *
+ * @return the unique name of teh sender
+ */
+gchar *
+dbus_g_method_get_sender (DBusGMethodInvocation *context)
+{
+ const gchar *sender;
+
+ sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
+
+ if (sender == NULL)
+ return NULL;
+
+ return strdup (sender);
+}
+
+/**
+ * Get the reply message to append reply values
+ * Used as a sidedoor when you can't generate dbus values
+ * of the correct type due to glib binding limitations
+ *
+ * @param context the method context
+ */
+DBusMessage *
+dbus_g_method_get_reply (DBusGMethodInvocation *context)
+{
+ return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
+}
+
+/**
+ * Send a manually created reply message
+ * Used as a sidedoor when you can't generate dbus values
+ * of the correct type due to glib binding limitations
+ *
+ * @param context the method context
+ * @param reply the reply message, will be unreffed
+ */
+void
+dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
+{
+ dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
+ dbus_message_unref (reply);
+
+ dbus_g_connection_unref (context->connection);
+ dbus_g_message_unref (context->message);
+ g_free (context);
+}
+
+
+/**
* Send a return message for a given method invocation, with arguments.
* This function also frees the sending context.
*
reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
out_sig = method_output_signature_from_object_info (context->object, context->method);
- argsig = dbus_gtypes_from_arg_signature (out_sig, FALSE);
+ argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
dbus_message_iter_init_append (reply, &iter);
g_warning(error);
g_free (error);
}
- dbus_gvalue_marshal (&iter, &value);
+ _dbus_gvalue_marshal (&iter, &value);
}
va_end (args);
#ifdef DBUS_BUILD_TESTS
#include <stdlib.h>
+static void
+_dummy_function (void)
+{
+}
+
+/* Data structures copied from one generated by current dbus-binding-tool;
+ * we need to support this layout forever
+ */
+static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
+ { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
+};
+
+const DBusGObjectInfo dbus_glib_internal_test_object_info = {
+ 0,
+ dbus_glib_internal_test_methods,
+ 30,
+"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",
+"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",
+"\0"
+};
+
+
/**
* @ingroup DBusGLibInternals
* Unit test for GLib GObject integration ("skeletons")
_dbus_gobject_test (const char *test_data_dir)
{
int i;
+ const char *arg;
+ const char *arg_name;
+ gboolean arg_in;
+ gboolean constval;
+ RetvalType retval;
+ const char *arg_signature;
+ const char *sigdata;
+ const char *iface;
+ const char *signame;
+
static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
{ "SetFoo", "set_foo" },
{ "Foo", "foo" },
/* { "FrobateUIHandler", "frobate_ui_handler" } */
};
+ /* Test lookup in our hardcoded object info; if these tests fail
+ * then it likely means you changed the generated object info in an
+ * incompatible way and broke the lookup functions. In that case
+ * you need to bump the version and use a new structure instead. */
+ /* DoNothing */
+ arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
+ &(dbus_glib_internal_test_methods[0]));
+ g_assert (*arg == '\0');
+
+ /* Increment */
+ arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
+ &(dbus_glib_internal_test_methods[1]));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (!strcmp (arg_name, "x"));
+ g_assert (arg_in == TRUE);
+ g_assert (!strcmp (arg_signature, "u"));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (arg_in == FALSE);
+ g_assert (retval == RETVAL_NONE);
+ g_assert (!strcmp (arg_signature, "u"));
+ g_assert (*arg == '\0');
+
+ /* IncrementRetval */
+ arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
+ &(dbus_glib_internal_test_methods[2]));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (!strcmp (arg_name, "x"));
+ g_assert (arg_in == TRUE);
+ g_assert (!strcmp (arg_signature, "u"));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (retval == RETVAL_NOERROR);
+ g_assert (arg_in == FALSE);
+ g_assert (!strcmp (arg_signature, "u"));
+ g_assert (*arg == '\0');
+
+ /* IncrementRetvalError */
+ arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
+ &(dbus_glib_internal_test_methods[3]));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (!strcmp (arg_name, "x"));
+ g_assert (arg_in == TRUE);
+ g_assert (!strcmp (arg_signature, "u"));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (retval == RETVAL_ERROR);
+ g_assert (arg_in == FALSE);
+ g_assert (!strcmp (arg_signature, "u"));
+ g_assert (*arg == '\0');
+
+ /* Stringify */
+ arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
+ &(dbus_glib_internal_test_methods[8]));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (!strcmp (arg_name, "val"));
+ g_assert (arg_in == TRUE);
+ g_assert (!strcmp (arg_signature, "v"));
+ g_assert (*arg != '\0');
+ arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
+ g_assert (retval == RETVAL_NONE);
+ g_assert (arg_in == FALSE);
+ g_assert (!strcmp (arg_signature, "s"));
+ g_assert (*arg == '\0');
+
+ sigdata = dbus_glib_internal_test_object_info.exported_signals;
+ g_assert (*sigdata != '\0');
+ sigdata = propsig_iterate (sigdata, &iface, &signame);
+ g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
+ g_assert (!strcmp (signame, "Frobnicate"));
+ g_assert (*sigdata != '\0');
+ sigdata = propsig_iterate (sigdata, &iface, &signame);
+ g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
+ g_assert (!strcmp (signame, "Sig0"));
+ g_assert (*sigdata != '\0');
+ sigdata = propsig_iterate (sigdata, &iface, &signame);
+ g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
+ g_assert (!strcmp (signame, "Sig1"));
+ g_assert (*sigdata != '\0');
+ sigdata = propsig_iterate (sigdata, &iface, &signame);
+ g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
+ g_assert (!strcmp (signame, "Sig2"));
+ g_assert (*sigdata == '\0');
+
+
i = 0;
while (i < (int) G_N_ELEMENTS (name_pairs))
{