diff options
author | Colin Walters <walters@verbum.org> | 2005-07-10 22:54:19 +0000 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2005-07-10 22:54:19 +0000 |
commit | 8c095eea8fbe2f8c219bdb2aebcf61e4e3993f53 (patch) | |
tree | af9030f8b45381f290c89b793e067a588c6d6353 /glib/dbus-binding-tool-glib.c | |
parent | 745b19d640e657118b298c6b7cc37798af878a5a (diff) |
2005-07-10 Colin Walters <walters@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.
Diffstat (limited to 'glib/dbus-binding-tool-glib.c')
-rw-r--r-- | glib/dbus-binding-tool-glib.c | 324 |
1 files changed, 222 insertions, 102 deletions
diff --git a/glib/dbus-binding-tool-glib.c b/glib/dbus-binding-tool-glib.c index f161c638..43b23c6d 100644 --- a/glib/dbus-binding-tool-glib.c +++ b/glib/dbus-binding-tool-glib.c @@ -62,6 +62,8 @@ dbus_g_type_get_marshal_name (GType gtype) { 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 @@ dbus_g_type_get_c_name (GType gtype) 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 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error) 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 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error) { ArgInfo *arg; char direction; + const char *returnval_annotation; arg = args->data; @@ -561,17 +612,86 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error) 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'); |