dbus/glib dbus-gvalue-utils.h, 1.2, 1.3 dbus-gvalue-utils.c, 1.3,
1.4 dbus-gobject.c, 1.42, 1.43 dbus-binding-tool-glib.h, 1.6,
1.7 dbus-binding-tool-glib.c, 1.18, 1.19 Makefile.am, 1.22, 1.23
Colin Walters
walters at freedesktop.org
Mon Jul 11 08:54:21 EST 2005
Update of /cvs/dbus/dbus/glib
In directory gabe:/tmp/cvs-serv16516/glib
Modified Files:
dbus-gvalue-utils.h dbus-gvalue-utils.c dbus-gobject.c
dbus-binding-tool-glib.h dbus-binding-tool-glib.c Makefile.am
Log Message:
2005-07-10 Colin Walters <walters at verbum.org>
* doc/TODO: Knock off some GLib items with this patch.
* glib/dbus-gvalue-utils.c (_dbus_gtype_can_signal_error)
(_dbus_gvalue_signals_error): New functions.
* glib/dbus-gvalue-utils.h: Prototype them.
* glib/dbus-gobject.c (arg_iterate): Update to handle return vals
and change to not output const/retval flags for input args. All
callers updated.
(invoke_object_method): Refactor to handle return values. Add
some more comments in various places. Remove debug g_print.
* glib/dbus-binding-tool-glib.h (DBUS_GLIB_ANNOTATION_RETURNVAL): New.
* glib/dbus-binding-tool-glib.c (dbus_g_type_get_marshal_name):
Handle G_TYPE_NONE.
(compute_gsignature): New function; refactored from code from
compute_marshaller and compute_marshaller_name. Enhance to
handle return values and async ops more cleanly. Update for
async ops returning NONE instead of BOOLEAN.
(compute_marshaller, compute_marshaller_name): Call compute_gsignature
and output appropriate string.
(generate_glue): Handle return value annotation. Also don't dump
constness flag for input arguments.
* glib/Makefile.am (DBUS_GLIB_INTERNALS): New variable; contains
files shared between installed library and utilities.
(libdbus_glib_1_la_SOURCES): Move some stuf into DBUS_GLIB_INTERNALS.
(libdbus_gtool_la_SOURCES): Suck in DBUS_GLIB_INTERNALS so the
binding tool can access gtype utility functions.
* test/glib/test-service-glib.c:
* test/glib/test-service-glib.xml:
* test/glib/test-dbus-glib.c: Add some tests for return values.
Index: dbus-gvalue-utils.h
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-gvalue-utils.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- dbus-gvalue-utils.h 8 Jul 2005 16:25:36 -0000 1.2
+++ dbus-gvalue-utils.h 10 Jul 2005 22:54:18 -0000 1.3
@@ -64,6 +64,10 @@
gboolean dbus_gvalue_take (GValue *value,
GTypeCValue *cvalue);
+gboolean _dbus_gtype_can_signal_error (GType gtype);
+gboolean _dbus_gvalue_signals_error (const GValue *value);
+
+
G_END_DECLS
#endif
Index: dbus-gvalue-utils.c
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-gvalue-utils.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- dbus-gvalue-utils.c 9 Jul 2005 01:46:51 -0000 1.3
+++ dbus-gvalue-utils.c 10 Jul 2005 22:54:18 -0000 1.4
@@ -206,6 +206,58 @@
return TRUE;
}
+gboolean
+_dbus_gtype_can_signal_error (GType gtype)
+{
+ switch (gtype)
+ {
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ case G_TYPE_STRING:
+ case G_TYPE_BOXED:
+ case G_TYPE_OBJECT:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+gboolean
+_dbus_gvalue_signals_error (const GValue *value)
+{
+ /* Hardcoded rules for return value semantics for certain
+ * types. Perhaps in the future we'd want an annotation
+ * specifying which return values are errors, but in
+ * reality people will probably just use boolean and
+ * boxed, and there the semantics are pretty standard.
+ */
+ switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
+ {
+ case G_TYPE_BOOLEAN:
+ return (g_value_get_boolean (value) == FALSE);
+ break;
+ case G_TYPE_INT:
+ return (g_value_get_int (value) < 0);
+ break;
+ case G_TYPE_UINT:
+ return (g_value_get_uint (value) == 0);
+ break;
+ case G_TYPE_STRING:
+ return (g_value_get_string (value) == NULL);
+ break;
+ case G_TYPE_BOXED:
+ return (g_value_get_boxed (value) == NULL);
+ break;
+ case G_TYPE_OBJECT:
+ return (g_value_get_boxed (value) == NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+
static gboolean
hash_func_from_gtype (GType gtype, GHashFunc *func)
{
@@ -1061,4 +1113,6 @@
return TRUE;
}
+
+
#endif /* DBUS_BUILD_TESTS */
Index: dbus-gobject.c
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-gobject.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- dbus-gobject.c 9 Jul 2005 18:54:45 -0000 1.42
+++ dbus-gobject.c 10 Jul 2005 22:54:18 -0000 1.43
@@ -143,45 +143,91 @@
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,
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 '%c'", *data);
+ inarg = FALSE;
break;
}
+ if (in)
+ *in = inarg;
- data = string_table_next (data);
- switch (*data)
+ if (!inarg)
{
- case 'F':
- *constval = FALSE;
- break;
- case 'C':
- *constval = TRUE;
- break;
- default:
- g_warning ("invalid arg const value '%c'", *data);
- break;
+ 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);
}
@@ -202,10 +248,9 @@
{
const char *name;
gboolean arg_in;
- gboolean constval;
const char *type;
- arg = arg_iterate (arg, &name, &arg_in, &constval, &type);
+ arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
if (arg_in == in)
g_string_append (ret, type);
@@ -340,10 +385,9 @@
{
const char *name;
gboolean arg_in;
- gboolean constval;
const char *type;
- args = arg_iterate (args, &name, &arg_in, &constval, &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",
@@ -846,15 +890,17 @@
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;
@@ -866,6 +912,11 @@
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
@@ -924,21 +975,72 @@
}
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)
{
- out_param_count++;
- dbus_signature_iter_next (&out_signature_iter);
+ 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++;
+ }
}
- /* 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.
+ /* 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)
+ {
+ 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
+ * (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);
@@ -948,16 +1050,32 @@
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);
@@ -971,17 +1089,20 @@
out_param_gvalue_pos++;
}
g_value_array_append (value_array, &value);
- dbus_signature_iter_next (&out_signature_iter);
}
+ }
- /* Append GError as final argument */
+ /* 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);
@@ -990,22 +1111,35 @@
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)
{
DBusMessageIter iter;
- const char *arg_metadata;
-
- /* Grab the argument metadata and iterate over it */
- arg_metadata = method_arg_info_from_object_info (object_info, method);
reply = dbus_message_new_method_return (message);
if (reply == NULL)
goto nomem;
- /* Append OUT arguments to reply */
+ /* Append output arguments to reply */
dbus_message_iter_init_append (reply, &iter);
+
+ /* 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 (*arg_metadata)
@@ -1014,26 +1148,26 @@
const char *arg_name;
gboolean arg_in;
gboolean constval;
+ RetvalType retval;
const char *arg_signature;
DBusSignatureIter argsigiter;
do
{
- /* Look for constness; skip over input arguments */
- arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &arg_signature);
+ /* 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 && *arg_metadata);
+ while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
- /* If the last argument we saw was input, we must be done iterating over
- * output arguments.
+ /* If the last argument we saw was input or the return
+ * value, we must be done iterating over output arguments.
*/
- if (arg_in)
+ if (arg_in || retval != RETVAL_NONE)
break;
dbus_signature_iter_init (&argsigiter, arg_signature);
- g_print ("looking at arg %s (%s)\n", arg_name, constval ? "TRUE" : "FALSE");
-
g_value_init (&gvalue, dbus_gtype_from_signature_iter (&argsigiter, FALSE));
if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
{
@@ -1070,14 +1204,12 @@
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_array_free (value_array);
- g_value_unset (&return_value);
return result;
nomem:
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
Index: dbus-binding-tool-glib.h
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-binding-tool-glib.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- dbus-binding-tool-glib.h 9 Jul 2005 17:52:52 -0000 1.6
+++ dbus-binding-tool-glib.h 10 Jul 2005 22:54:18 -0000 1.7
@@ -28,6 +28,7 @@
#define DBUS_GLIB_ANNOTATION_C_SYMBOL "org.freedesktop.DBus.GLib.CSymbol"
#define DBUS_GLIB_ANNOTATION_ASYNC "org.freedesktop.DBus.GLib.Async"
#define DBUS_GLIB_ANNOTATION_CONST "org.freedesktop.DBus.GLib.Const"
+#define DBUS_GLIB_ANNOTATION_RETURNVAL "org.freedesktop.DBus.GLib.ReturnVal"
gboolean dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, gboolean ignore_unsupported, GError **error);
gboolean dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, const char *prefix, GError **error);
Index: dbus-binding-tool-glib.c
===================================================================
RCS file: /cvs/dbus/dbus/glib/dbus-binding-tool-glib.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- dbus-binding-tool-glib.c 9 Jul 2005 18:54:45 -0000 1.18
+++ dbus-binding-tool-glib.c 10 Jul 2005 22:54:18 -0000 1.19
@@ -62,6 +62,8 @@
{
switch (G_TYPE_FUNDAMENTAL (gtype))
{
+ case G_TYPE_NONE:
+ return "NONE";
case G_TYPE_BOOLEAN:
return "BOOLEAN";
case G_TYPE_UCHAR:
@@ -112,148 +114,195 @@
return g_type_name (gtype);
}
-static char *
-compute_marshaller (MethodInfo *method, GError **error)
+static gboolean
+compute_gsignature (MethodInfo *method, GType *rettype, GArray **params, GError **error)
{
GSList *elt;
- GString *ret;
- gboolean first;
+ GType retval_type;
+ GArray *ret;
+ gboolean is_async;
+ const char *arg_type;
+ gboolean retval_signals_error;
+
+ is_async = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL;
+ retval_signals_error = FALSE;
- /* All methods required to return boolean for now;
- * will be conditional on method info later */
- ret = g_string_new ("BOOLEAN:");
+ ret = g_array_new (TRUE, TRUE, sizeof (GType));
- first = TRUE;
- /* Append input arguments */
- for (elt = method_info_get_args (method); elt; elt = elt->next)
+ if (is_async)
+ retval_type = G_TYPE_NONE;
+ else
{
- ArgInfo *arg = elt->data;
+ gboolean found_retval;
- if (arg_info_get_direction (arg) == ARG_IN)
+ /* Look for return value */
+ found_retval = FALSE;
+ for (elt = method_info_get_args (method); elt; elt = elt->next)
{
- const char *marshal_name;
- GType gtype;
-
- gtype = dbus_gtype_from_signature (arg_info_get_type (arg), FALSE);
- if (gtype == G_TYPE_INVALID)
+ ArgInfo *arg = elt->data;
+ const char *returnval_annotation;
+
+ returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
+ if (returnval_annotation != NULL)
{
- g_set_error (error,
- DBUS_BINDING_TOOL_ERROR,
- DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
- _("Unsupported conversion from D-BUS type %s to glib-genmarshal type"),
- arg_info_get_type (arg));
- g_string_free (ret, TRUE);
- return NULL;
+ arg_type = arg_info_get_type (arg);
+ retval_type = dbus_gtype_from_signature (arg_type, FALSE);
+ if (retval_type == G_TYPE_INVALID)
+ goto invalid_type;
+ found_retval = TRUE;
+ if (!strcmp (returnval_annotation, "error"))
+ retval_signals_error = TRUE;
+ break;
}
-
- marshal_name = dbus_g_type_get_marshal_name (gtype);
- g_assert (marshal_name);
-
- if (!first)
- g_string_append (ret, ",");
- else
- first = FALSE;
- g_string_append (ret, marshal_name);
+ }
+ if (!found_retval)
+ {
+ retval_type = G_TYPE_BOOLEAN;
+ retval_signals_error = TRUE;
}
}
- if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL)
+ *rettype = retval_type;
+
+ /* Handle all input arguments */
+ for (elt = method_info_get_args (method); elt; elt = elt->next)
{
- if (!first)
- g_string_append (ret, ",");
- g_string_append (ret, "POINTER");
- first = FALSE;
+ ArgInfo *arg = elt->data;
+ if (arg_info_get_direction (arg) == ARG_IN)
+ {
+ GType gtype;
+
+ arg_type = arg_info_get_type (arg);
+ gtype = dbus_gtype_from_signature (arg_type, FALSE);
+ if (gtype == G_TYPE_INVALID)
+ goto invalid_type;
+
+ g_array_append_val (ret, gtype);
+ }
}
- else
+
+ if (!is_async)
{
/* Append pointer for each out arg storage */
for (elt = method_info_get_args (method); elt; elt = elt->next)
{
ArgInfo *arg = elt->data;
+ /* Skip return value */
+ if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL) != NULL)
+ continue;
+
if (arg_info_get_direction (arg) == ARG_OUT)
{
- if (!first)
- g_string_append (ret, ",");
- else
- first = FALSE;
- g_string_append (ret, "POINTER");
+ GType gtype;
+ arg_type = arg_info_get_type (arg);
+ gtype = dbus_gtype_from_signature (arg_type, FALSE);
+ if (gtype == G_TYPE_INVALID)
+ goto invalid_type;
+ /* We actually just need a pointer for the return value
+ storage */
+ gtype = G_TYPE_POINTER;
+ g_array_append_val (ret, gtype);
}
}
- /* Final GError parameter */
- if (!first)
- g_string_append (ret, ",");
- g_string_append (ret, "POINTER");
+ if (retval_signals_error)
+ {
+ /* Final GError parameter */
+ GType gtype = G_TYPE_POINTER;
+ g_array_append_val (ret, gtype);
+ }
+ }
+ else
+ {
+ /* Context pointer */
+ GType gtype = G_TYPE_POINTER;
+ g_array_append_val (ret, gtype);
}
- return g_string_free (ret, FALSE);
+ *params = ret;
+ return TRUE;
+ invalid_type:
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+ _("Unsupported conversion from D-BUS type %s to glib-genmarshal type"),
+ arg_type);
+ return FALSE;
}
+
static char *
-compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error)
+compute_marshaller (MethodInfo *method, GError **error)
{
- GSList *elt;
+ GArray *signature;
+ GType rettype;
+ const char *marshal_name;
GString *ret;
+ guint i;
- /* All methods required to return boolean for now;
- * will be conditional on method info later */
- ret = g_string_new (MARSHAL_PREFIX);
- g_string_append (ret, prefix);
- g_string_append (ret, "_BOOLEAN_");
+ if (!compute_gsignature (method, &rettype, &signature, error))
+ return NULL;
- /* Append input arguments */
- for (elt = method_info_get_args (method); elt; elt = elt->next)
+ ret = g_string_new ("");
+ marshal_name = dbus_g_type_get_marshal_name (rettype);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ g_string_append_c (ret, ':');
+ for (i = 0; i < signature->len; i++)
{
- ArgInfo *arg = elt->data;
+ marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ if (i < signature->len - 1)
+ g_string_append_c (ret, ',');
+ }
+ if (signature->len == 0)
+ {
+ marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ }
+ g_array_free (signature, TRUE);
+ return g_string_free (ret, FALSE);
+}
- if (arg_info_get_direction (arg) == ARG_IN)
- {
- const char *marshal_name;
- const char *type;
- GType gtype;
+static char *
+compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error)
+{
+ GString *ret;
+ GArray *signature;
+ GType rettype;
+ const char *marshal_name;
+ guint i;
- type = arg_info_get_type (arg);
- gtype = dbus_gtype_from_signature (type, FALSE);
- if (gtype == G_TYPE_INVALID)
- {
- g_set_error (error,
- DBUS_BINDING_TOOL_ERROR,
- DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
- _("Unsupported conversion from D-BUS type %s to glib type"),
- type);
- g_string_free (ret, TRUE);
- return NULL;
- }
- marshal_name = dbus_g_type_get_marshal_name (gtype);
- g_assert (marshal_name != NULL);
+ if (!compute_gsignature (method, &rettype, &signature, error))
+ return NULL;
- g_string_append (ret, "_");
- g_string_append (ret, marshal_name);
- }
- }
+ ret = g_string_new (MARSHAL_PREFIX);
+ g_string_append (ret, prefix);
+ g_string_append_c (ret, '_');
- if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL)
+ marshal_name = dbus_g_type_get_marshal_name (rettype);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ g_string_append (ret, "__");
+ for (i = 0; i < signature->len; i++)
{
- g_string_append (ret, "_POINTER");
+ marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
+ if (i < signature->len - 1)
+ g_string_append_c (ret, '_');
}
- else
+ if (signature->len == 0)
{
- /* Append pointer for each out arg storage */
- for (elt = method_info_get_args (method); elt; elt = elt->next)
- {
- ArgInfo *arg = elt->data;
-
- if (arg_info_get_direction (arg) == ARG_OUT)
- {
- g_string_append (ret, "_POINTER");
- }
- }
- /* Final GError parameter */
- g_string_append (ret, "_POINTER");
+ marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
+ g_assert (marshal_name != NULL);
+ g_string_append (ret, marshal_name);
}
-
+ g_array_free (signature, TRUE);
return g_string_free (ret, FALSE);
}
@@ -482,6 +531,7 @@
char *method_c_name;
gboolean async = FALSE;
GSList *args;
+ gboolean found_retval = FALSE;
method = (MethodInfo *) tmp->data;
method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL));
@@ -531,6 +581,7 @@
{
ArgInfo *arg;
char direction;
+ const char *returnval_annotation;
arg = args->data;
@@ -561,17 +612,86 @@
g_set_error (error,
DBUS_BINDING_TOOL_ERROR,
DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
- "Input argument \"%s\" has const annotation in method \"%s\" of interface \"%s\"\n",
+ "Input argument \"%s\" cannot have const annotation in method \"%s\" of interface \"%s\"\n",
arg_info_get_name (arg),
method_info_get_name (method),
interface_info_get_name (interface));
return FALSE;
}
g_string_append_c (object_introspection_data_blob, 'C');
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+ else if (arg_info_get_direction (arg) == ARG_OUT)
+ {
+ g_string_append_c (object_introspection_data_blob, 'F');
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+
+ returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
+ if (returnval_annotation != NULL)
+ {
+ GType gtype;
+
+ if (found_retval)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Multiple arguments with return value annotation in method \"%s\" of interface \"%s\"\n",
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+ found_retval = TRUE;
+ if (arg_info_get_direction (arg) == ARG_IN)
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Input argument \"%s\" cannot have return value annotation in method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+ if (!strcmp ("", returnval_annotation))
+ g_string_append_c (object_introspection_data_blob, 'R');
+ else if (!strcmp ("error", returnval_annotation))
+ {
+ gtype = dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+ if (!_dbus_gtype_can_signal_error (gtype))
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Output argument \"%s\" cannot signal error with type \"%s\" in method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ g_type_name (gtype),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+ g_string_append_c (object_introspection_data_blob, 'E');
+ }
+ else
+ {
+ g_set_error (error,
+ DBUS_BINDING_TOOL_ERROR,
+ DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+ "Invalid ReturnVal annotation for argument \"%s\" in method \"%s\" of interface \"%s\"\n",
+ arg_info_get_name (arg),
+ method_info_get_name (method),
+ interface_info_get_name (interface));
+ return FALSE;
+ }
+
+ g_string_append_c (object_introspection_data_blob, '\0');
+ }
+ else if (arg_info_get_direction (arg) == ARG_OUT)
+ {
+ g_string_append_c (object_introspection_data_blob, 'N');
+ g_string_append_c (object_introspection_data_blob, '\0');
}
- else
- g_string_append_c (object_introspection_data_blob, 'F');
- g_string_append_c (object_introspection_data_blob, '\0');
g_string_append (object_introspection_data_blob, arg_info_get_type (arg));
g_string_append_c (object_introspection_data_blob, '\0');
Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/glib/Makefile.am,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- Makefile.am 26 Jun 2005 17:02:09 -0000 1.22
+++ Makefile.am 10 Jul 2005 22:54:19 -0000 1.23
@@ -11,6 +11,13 @@
CLEANFILES = $(BUILT_SOURCES)
+DBUS_GLIB_INTERNALS = \
+ dbus-gtype-specialized.c \
+ dbus-gutils.c \
+ dbus-gutils.h \
+ dbus-gvalue-utils.c \
+ dbus-gvalue-utils.h
+
libdbus_glib_1_la_SOURCES = \
dbus-glib-error-switch.h \
dbus-glib.c \
@@ -23,13 +30,9 @@
dbus-gtest.c \
dbus-gtest.h \
dbus-gthread.c \
- dbus-gutils.c \
- dbus-gutils.h \
dbus-gvalue.c \
- dbus-gtype-specialized.c \
dbus-gvalue.h \
- dbus-gvalue-utils.c \
- dbus-gvalue-utils.h
+ $(DBUS_GLIB_INTERNALS)
libdbus_glib_HEADERS = \
dbus-gtype-specialized.h
@@ -44,14 +47,12 @@
# convenience lib used here and by dbus-viewer
noinst_LTLIBRARIES=libdbus-gtool.la
-libdbus_gtool_la_SOURCES = \
+libdbus_gtool_la_SOURCES = $(DBUS_GLIB_INTERNALS) \
dbus-gidl.c \
dbus-gidl.h \
dbus-gloader-expat.c \
dbus-gparser.c \
- dbus-gparser.h \
- dbus-gutils.c \
- dbus-gutils.h
+ dbus-gparser.h
libdbus_gtool_la_LIBADD = libdbus-glib-1.la
More information about the dbus-commit
mailing list