diff options
| author | Colin Walters <walters@verbum.org> | 2005-03-09 17:09:11 +0000 | 
|---|---|---|
| committer | Colin Walters <walters@verbum.org> | 2005-03-09 17:09:11 +0000 | 
| commit | 74b1b35402f6b9bbc09999a6224dfc04bc48b2a9 (patch) | |
| tree | c9cae2dde5d4b11d4cf7e17e5c3009280e1f8ee5 | |
| parent | 2958e723fc996e2dd7edfdc6ac53dcdf48323549 (diff) | |
2005-03-09  Colin Walters  <walters@verbum.org>
	* glib/dbus-gproxy.c (dbus_g_proxy_invoke): New method; calls
	to this are generated for client-side wrappers.  Invokes a
	D-BUS method and returns reply values.
	* glib/dbus-binding-tool-glib.c (write_args_sig_for_direction): New
	function; writes signature string for argument direction.
	(write_args_for_direction): Change to pass input values directly
	instead of via address, and fix indentation.
	(generate_client_glue): Change to invoke dbus_g_proxy_invoke.  Also
	make generated wrappers inlineable.
	* dbus/dbus-message.c (dbus_message_iter_get_fixed_array): Add
	note about using dbus_type_is_fixed.
	* dbus/dbus-marshal-basic.c (_dbus_type_is_fixed): Moved to
	dbus/dbus-signature.c as dbus_type_is_fixed.
	All callers updated.
	* dbus/dbus-signature.c (dbus_type_is_fixed): Moved here
	from dbus/dbus-marshal-basic.c:_dbus_type_is_fixed.
	* dbus/dbus-signature.h: Prototype.
	* glib/dbus-binding-tool-glib.c (compute_marshaller_name): Fix
	error printf code.
	* test/glib/test-dbus-glib.c (main): Be sure to clear error as
	appropriate instead of just freeing it.
	(main): Free returned strings using g_free.
	* test/glib/Makefile.am (test-service-glib-glue.h)
	(test-service-glib-bindings.h): Add dependency on dbus-binding-tool.
	* glib/dbus-gvalue.c (MAP_BASIC): Refactored from MAP_BASIC_INIT;
	simply maps a simple D-BUS type to GType.
	(dbus_dbus_type_to_gtype): Function which maps D-BUS type to
	GType.
	(dbus_gvalue_init): Just invoke dbus_dbus_type_to_gtype and
	initialize the value with it.
	(dbus_gvalue_binding_type_from_type): Unused, delete.
	(dbus_gvalue_demarshal): Switch to hardcoding demarshalling for
	various types instead of unmarshalling to value data directly.
	Remove can_convert boolean.
	(dbus_gvalue_marshal): Remove duplicate initialization; switch to
	returning directly instead of using can_convert boolean.
	(dbus_gvalue_store): New function; not related to D-BUS per-se.
	Stores a GValue in a pointer to a value of its corresponding C
	type.
	* glib/dbus-gvalue.h: Remove dbus_gvalue_binding_type_from_type,
	add dbus_gvalue_store.
| -rw-r--r-- | ChangeLog | 55 | ||||
| -rw-r--r-- | dbus/dbus-glib.h | 7 | ||||
| -rw-r--r-- | dbus/dbus-marshal-basic.c | 34 | ||||
| -rw-r--r-- | dbus/dbus-marshal-byteswap.c | 3 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive-util.c | 4 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive.c | 8 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 11 | ||||
| -rw-r--r-- | dbus/dbus-signature.c | 30 | ||||
| -rw-r--r-- | dbus/dbus-signature.h | 1 | ||||
| -rw-r--r-- | glib/dbus-binding-tool-glib.c | 73 | ||||
| -rw-r--r-- | glib/dbus-gproxy.c | 205 | ||||
| -rw-r--r-- | glib/dbus-gvalue.c | 254 | ||||
| -rw-r--r-- | glib/dbus-gvalue.h | 4 | ||||
| -rw-r--r-- | test/glib/Makefile.am | 4 | ||||
| -rw-r--r-- | test/glib/test-dbus-glib.c | 6 | 
15 files changed, 509 insertions, 190 deletions
| @@ -1,3 +1,58 @@ +2005-03-09  Colin Walters  <walters@verbum.org> + +	* glib/dbus-gproxy.c (dbus_g_proxy_invoke): New method; calls +	to this are generated for client-side wrappers.  Invokes a +	D-BUS method and returns reply values.   + +	* glib/dbus-binding-tool-glib.c (write_args_sig_for_direction): New +	function; writes signature string for argument direction. +	(write_args_for_direction): Change to pass input values directly +	instead of via address, and fix indentation. +	(generate_client_glue): Change to invoke dbus_g_proxy_invoke.  Also +	make generated wrappers inlineable. + +	* dbus/dbus-message.c (dbus_message_iter_get_fixed_array): Add +	note about using dbus_type_is_fixed. + +	* dbus/dbus-marshal-basic.c (_dbus_type_is_fixed): Moved to +	dbus/dbus-signature.c as dbus_type_is_fixed. + +	All callers updated. + +	* dbus/dbus-signature.c (dbus_type_is_fixed): Moved here +	from dbus/dbus-marshal-basic.c:_dbus_type_is_fixed. + +	* dbus/dbus-signature.h: Prototype. + +	* glib/dbus-binding-tool-glib.c (compute_marshaller_name): Fix +	error printf code. + +	* test/glib/test-dbus-glib.c (main): Be sure to clear error as +	appropriate instead of just freeing it. +	(main): Free returned strings using g_free. + +	* test/glib/Makefile.am (test-service-glib-glue.h) +	(test-service-glib-bindings.h): Add dependency on dbus-binding-tool. + +	* glib/dbus-gvalue.c (MAP_BASIC): Refactored from MAP_BASIC_INIT; +	simply maps a simple D-BUS type to GType. +	(dbus_dbus_type_to_gtype): Function which maps D-BUS type to +	GType. +	(dbus_gvalue_init): Just invoke dbus_dbus_type_to_gtype and +	initialize the value with it. +	(dbus_gvalue_binding_type_from_type): Unused, delete. +	(dbus_gvalue_demarshal): Switch to hardcoding demarshalling for +	various types instead of unmarshalling to value data directly. +	Remove can_convert boolean. +	(dbus_gvalue_marshal): Remove duplicate initialization; switch to +	returning directly instead of using can_convert boolean. +	(dbus_gvalue_store): New function; not related to D-BUS per-se. +	Stores a GValue in a pointer to a value of its corresponding C +	type. + +	* glib/dbus-gvalue.h: Remove dbus_gvalue_binding_type_from_type, +	add dbus_gvalue_store. +  2005-03-08  Joe Shaw  <joeshaw@novell.com>  	Fix a bunch of lifecycle and memory management problems diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h index a9aad540..e1b4a704 100644 --- a/dbus/dbus-glib.h +++ b/dbus/dbus-glib.h @@ -174,6 +174,13 @@ void              dbus_g_proxy_call_no_reply         (DBusGProxy        *proxy,  const char*       dbus_g_proxy_get_bus_name          (DBusGProxy        *proxy); +gboolean          dbus_g_proxy_invoke                (DBusGProxy        *proxy, +						      const char        *method, +						      const char        *insig, +						      const char        *outsig, +						      GError           **error, +						      ...); +  #undef DBUS_INSIDE_DBUS_GLIB_H  G_END_DECLS diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c index fde58d51..ea0648ae 100644 --- a/dbus/dbus-marshal-basic.c +++ b/dbus/dbus-marshal-basic.c @@ -620,7 +620,7 @@ _dbus_marshal_read_fixed_multi  (const DBusString *str,    int array_len;    int alignment; -  _dbus_assert (_dbus_type_is_fixed (element_type)); +  _dbus_assert (dbus_type_is_fixed (element_type));    _dbus_assert (dbus_type_is_basic (element_type));  #if 0 @@ -1054,7 +1054,7 @@ marshal_fixed_multi (DBusString           *str,  /**   * Marshals a block of values of fixed-length type all at once, as an - * optimization.  _dbus_type_is_fixed() returns #TRUE for fixed-length + * optimization.  dbus_type_is_fixed() returns #TRUE for fixed-length   * types, which are the basic types minus the string-like types.   *   * The value argument should be the adddress of an @@ -1080,7 +1080,7 @@ _dbus_marshal_write_fixed_multi (DBusString *str,  {    const void* vp = *(const DBusBasicValue**)value; -  _dbus_assert (_dbus_type_is_fixed (element_type)); +  _dbus_assert (dbus_type_is_fixed (element_type));    _dbus_assert (n_elements >= 0);  #if 0 @@ -1299,34 +1299,6 @@ _dbus_type_is_valid (int typecode)  }  /** - * Tells you whether values of this type can change length if you set - * them to some other value. For this purpose, you assume that the - * first byte of the old and new value would be in the same location, - * so alignment padding is not a factor. - * - * @returns #FALSE if the type can occupy different lengths - */ -dbus_bool_t -_dbus_type_is_fixed (int typecode) -{ -  switch (typecode) -    { -    case DBUS_TYPE_BYTE: -    case DBUS_TYPE_BOOLEAN: -    case DBUS_TYPE_INT16: -    case DBUS_TYPE_UINT16: -    case DBUS_TYPE_INT32: -    case DBUS_TYPE_UINT32: -    case DBUS_TYPE_INT64: -    case DBUS_TYPE_UINT64: -    case DBUS_TYPE_DOUBLE: -      return TRUE; -    default: -      return FALSE; -    } -} - -/**   * Returns a string describing the given type.   *   * @param typecode the type to describe diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c index c8ec8942..7571e2fc 100644 --- a/dbus/dbus-marshal-byteswap.c +++ b/dbus/dbus-marshal-byteswap.c @@ -23,6 +23,7 @@  #include "dbus-marshal-byteswap.h"  #include "dbus-marshal-basic.h" +#include "dbus-signature.h"  /**   * @addtogroup DBusMarshal @@ -103,7 +104,7 @@ byteswap_body_helper (DBusTypeReader       *reader,                  p = _DBUS_ALIGN_ADDRESS (p, alignment); -                if (_dbus_type_is_fixed (elem_type)) +                if (dbus_type_is_fixed (elem_type))                    {                      if (alignment > 1)                        _dbus_swap_array (p, array_len / alignment, alignment); diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c index e1b00e58..0d06bc2f 100644 --- a/dbus/dbus-marshal-recursive-util.c +++ b/dbus/dbus-marshal-recursive-util.c @@ -3074,7 +3074,7 @@ array_write_value (TestTypeNode   *node,      goto oom;    if (arrays_write_fixed_in_blocks && -      _dbus_type_is_fixed (element_type) && +      dbus_type_is_fixed (element_type) &&        child->klass->write_multi)      {        if (!node_write_multi (child, block, &sub, seed, n_copies)) @@ -3138,7 +3138,7 @@ array_read_or_set_value (TestTypeNode   *node,        _dbus_type_reader_recurse (reader, &sub);        if (realign_root == NULL && arrays_write_fixed_in_blocks && -          _dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) && +          dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&            child->klass->read_multi)          {            if (!node_read_multi (child, &sub, seed, n_copies)) diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c index 432e6f0b..6fcbd623 100644 --- a/dbus/dbus-marshal-recursive.c +++ b/dbus/dbus-marshal-recursive.c @@ -1018,7 +1018,7 @@ _dbus_type_reader_read_fixed_multi (const DBusTypeReader  *reader,                                                  reader->type_pos);    _dbus_assert (element_type != DBUS_TYPE_INVALID); /* why we don't use get_current_type() */ -  _dbus_assert (_dbus_type_is_fixed (element_type)); +  _dbus_assert (dbus_type_is_fixed (element_type));    alignment = _dbus_type_get_alignment (element_type); @@ -1464,7 +1464,7 @@ _dbus_type_reader_set_basic (DBusTypeReader       *reader,    _dbus_assert (dbus_type_is_basic (current_type)); -  if (_dbus_type_is_fixed (current_type)) +  if (dbus_type_is_fixed (current_type))      {        reader_set_basic_fixed_length (reader, current_type, value);        return TRUE; @@ -2404,7 +2404,7 @@ _dbus_type_writer_write_basic (DBusTypeWriter *writer,  /**   * Writes a block of fixed-length basic values, i.e. those that are - * both _dbus_type_is_fixed() and _dbus_type_is_basic(). The block + * both dbus_type_is_fixed() and _dbus_type_is_basic(). The block   * must be written inside an array.   *   * The value parameter should be the address of said array of values, @@ -2423,7 +2423,7 @@ _dbus_type_writer_write_fixed_multi (DBusTypeWriter        *writer,                                       int                    n_elements)  {    _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY); -  _dbus_assert (_dbus_type_is_fixed (element_type)); +  _dbus_assert (dbus_type_is_fixed (element_type));    _dbus_assert (writer->type_pos_is_expectation);    _dbus_assert (n_elements >= 0); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 672a72b4..b090fab0 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -1270,7 +1270,7 @@ dbus_message_append_args_valist (DBusMessage *message,                                                   &array))              goto failed; -          if (_dbus_type_is_fixed (element_type)) +          if (dbus_type_is_fixed (element_type))              {                const DBusBasicValue **value;                int n_elements; @@ -1676,6 +1676,9 @@ dbus_message_iter_get_basic (DBusMessageIter  *iter,   * such as integers, bool, double. The block read will be from the   * current position in the array until the end of the array.   * + * This function should only be used if #dbus_type_is_fixed returns + * #TRUE for the element type. + *   * The value argument should be the address of a location to store the   * returned array. So for int32 it should be a "const dbus_int32_t**"   * The returned value is by reference and should not be freed. @@ -1693,7 +1696,7 @@ dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,    _dbus_return_if_fail (_dbus_message_iter_check (real));    _dbus_return_if_fail (value != NULL); -  _dbus_return_if_fail (_dbus_type_is_fixed (_dbus_type_reader_get_element_type (&real->u.reader))); +  _dbus_return_if_fail (dbus_type_is_fixed (_dbus_type_reader_get_element_type (&real->u.reader)));    _dbus_type_reader_read_fixed_multi (&real->u.reader,                                        value, n_elements); @@ -1778,7 +1781,7 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter,                goto out;              } -          if (_dbus_type_is_fixed (spec_element_type)) +          if (dbus_type_is_fixed (spec_element_type))              {                ptr = va_arg (var_args, const DBusBasicValue**);                n_elements_p = va_arg (var_args, int*); @@ -2138,7 +2141,7 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter,    _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);    _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); -  _dbus_return_val_if_fail (_dbus_type_is_fixed (element_type), FALSE); +  _dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE);    _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);    _dbus_return_val_if_fail (value != NULL, FALSE);    _dbus_return_val_if_fail (n_elements >= 0, FALSE); diff --git a/dbus/dbus-signature.c b/dbus/dbus-signature.c index 698c21ed..7cbae7c2 100644 --- a/dbus/dbus-signature.c +++ b/dbus/dbus-signature.c @@ -262,6 +262,36 @@ dbus_type_is_basic (int typecode)    return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));  } +/** + * Tells you whether values of this type can change length if you set + * them to some other value. For this purpose, you assume that the + * first byte of the old and new value would be in the same location, + * so alignment padding is not a factor. + * + * This function is useful to determine whether #dbus_message_iter_get_fixed_array + * may be used. + * + * @returns #FALSE if the type can occupy different lengths + */ +dbus_bool_t +dbus_type_is_fixed (int typecode) +{ +  switch (typecode) +    { +    case DBUS_TYPE_BYTE: +    case DBUS_TYPE_BOOLEAN: +    case DBUS_TYPE_INT16: +    case DBUS_TYPE_UINT16: +    case DBUS_TYPE_INT32: +    case DBUS_TYPE_UINT32: +    case DBUS_TYPE_INT64: +    case DBUS_TYPE_UINT64: +    case DBUS_TYPE_DOUBLE: +      return TRUE; +    default: +      return FALSE; +    } +}  #ifdef DBUS_BUILD_TESTS diff --git a/dbus/dbus-signature.h b/dbus/dbus-signature.h index 3c50795e..fd64ed11 100644 --- a/dbus/dbus-signature.h +++ b/dbus/dbus-signature.h @@ -65,6 +65,7 @@ dbus_bool_t     dbus_signature_validate_single       (const char       *signatur  dbus_bool_t     dbus_type_is_basic                   (int            typecode);  dbus_bool_t     dbus_type_is_container               (int            typecode); +dbus_bool_t     dbus_type_is_fixed                   (int            typecode);  DBUS_END_DECLS diff --git a/glib/dbus-binding-tool-glib.c b/glib/dbus-binding-tool-glib.c index 641f07da..5bd413e1 100644 --- a/glib/dbus-binding-tool-glib.c +++ b/glib/dbus-binding-tool-glib.c @@ -140,7 +140,7 @@ compute_marshaller_name (MethodInfo *method, GError **error)  	      g_set_error (error,  			   DBUS_BINDING_TOOL_ERROR,  			   DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION, -			   _("Unsupported conversion from D-BUS type %d to glib-genmarshal type"), +			   _("Unsupported conversion from D-BUS type %s to glib-genmarshal type"),  			   type);  	      g_string_free (ret, TRUE);  	      return NULL; @@ -647,42 +647,54 @@ write_formal_parameters (InterfaceInfo *iface, MethodInfo *method, GIOChannel *c  }  static gboolean -write_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error) +write_args_sig_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error)  {    GSList *args; +  WRITE_OR_LOSE ("\""); +    for (args = method_info_get_args (method); args; args = args->next)      {        ArgInfo *arg; -      const char *type_str;        arg = args->data;        if (direction != arg_info_get_direction (arg))  	continue; -      type_str = dbus_gvalue_binding_type_from_type (arg_info_get_type (arg)); -      if (!type_str) -	{ -	  g_set_error (error, -		       DBUS_BINDING_TOOL_ERROR, -		       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION, -		       _("Unsupported conversion from D-BUS type %s"), -		       arg_info_get_type (arg)); -	  return FALSE; -	} +      if (!write_printf_to_iochannel ("%s", channel, error, arg_info_get_type (arg))) +	goto io_lose; +    } + +  WRITE_OR_LOSE ("\", "); + +  return TRUE; + io_lose: +  return FALSE; +} + +static gboolean +write_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error) +{ +  GSList *args; + +  for (args = method_info_get_args (method); args; args = args->next) +    { +      ArgInfo *arg; + +      arg = args->data; + +      if (direction != arg_info_get_direction (arg)) +	continue; -              switch (direction)  	{  	case ARG_IN: -	  if (!write_printf_to_iochannel ("                                  %s, &IN_%s,\n", channel, error, -					  type_str, arg_info_get_name (arg))) +	  if (!write_printf_to_iochannel ("IN_%s, ", channel, error, arg_info_get_name (arg)))  	    goto io_lose;  	  break;  	case ARG_OUT: -	  if (!write_printf_to_iochannel ("                               %s, OUT_%s,\n", channel, error, -					  type_str, arg_info_get_name (arg))) +	  if (!write_printf_to_iochannel ("OUT_%s, ", channel, error, arg_info_get_name (arg)))  	    goto io_lose;  	  break;  	case ARG_INVALID: @@ -746,7 +758,7 @@ generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error  	  method_name = compute_client_method_name (interface, method); -	  WRITE_OR_LOSE ("static gboolean\n"); +	  WRITE_OR_LOSE ("static\n#ifdef G_HAVE_INLINE\ninline\n#endif\ngboolean\n");  	  if (!write_printf_to_iochannel ("%s (DBusGProxy *proxy", channel, error,  					  method_name))  	    goto io_lose; @@ -758,29 +770,26 @@ generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error  	  WRITE_OR_LOSE (", GError **error)\n\n");  	  WRITE_OR_LOSE ("{\n"); -	  WRITE_OR_LOSE ("  gboolean ret;\n\n"); -	  WRITE_OR_LOSE ("  DBusGPendingCall *call;\n\n"); -	  if (!write_printf_to_iochannel ("  call = dbus_g_proxy_begin_call (proxy, \"%s\",\n", -					  channel, error, +	  if (!write_printf_to_iochannel ("  return dbus_g_proxy_invoke (proxy, \"%s\", ", channel, error,  					  method_info_get_name (method)))  	    goto io_lose; -	  if (!write_args_for_direction (interface, method, channel, ARG_IN, error)) +	  if (!write_args_sig_for_direction (interface, method, channel, ARG_IN, error))  	    goto io_lose; -	  WRITE_OR_LOSE ("                                  DBUS_TYPE_INVALID);\n"); -	  WRITE_OR_LOSE ("  ret = dbus_g_proxy_end_call (proxy, call, error,\n"); -	   -	  if (!write_args_for_direction (interface, method, channel, ARG_OUT, error)) +	  if (!write_args_sig_for_direction (interface, method, channel, ARG_OUT, error))  	    goto io_lose; -	  WRITE_OR_LOSE ("                               DBUS_TYPE_INVALID);\n"); +	  WRITE_OR_LOSE ("error, "); -	  WRITE_OR_LOSE ("  dbus_g_pending_call_unref (call);\n"); -	  WRITE_OR_LOSE ("  return ret;\n"); +	  if (!write_args_for_direction (interface, method, channel, ARG_IN, error)) +	    goto io_lose; + +	  if (!write_args_for_direction (interface, method, channel, ARG_OUT, error)) +	    goto io_lose; -	  WRITE_OR_LOSE ("}\n\n"); +	  WRITE_OR_LOSE ("NULL);\n}\n\n");  	}      }    return TRUE; diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 65f14e12..b5e977a4 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -22,11 +22,14 @@   */  #include <dbus/dbus-glib.h>  #include <dbus/dbus-glib-lowlevel.h> +#include <dbus/dbus-signature.h>  #include "dbus-gutils.h"  #include "dbus-gmarshal.h"  #include "dbus-gvalue.h"  #include "dbus-gobject.h"  #include <string.h> +#include <glib/gi18n.h> +#include <gobject/gvaluecollector.h>  /**   * @addtogroup DBusGLibInternals @@ -1397,6 +1400,208 @@ dbus_g_proxy_end_call (DBusGProxy          *proxy,  }  /** + * Function for invoking a method and receiving reply values. + * Normally this is not used directly - calls to it are generated + * from client-side wrappers (see dbus-binding-tool). + * + * This function takes two type signatures, one for method arguments, + * and one for return values.  The remaining arguments after the + * error parameter should be values of the input arguments, + * followed by pointer values to storage for return values. + * + * @param proxy a proxy for a remote interface + * @param method method to invoke + * @param insig signature of input values + * @param outsig signature of output values + * @param error return location for an error + * @returns #FALSE if an error is set, TRUE otherwise + */ +gboolean +dbus_g_proxy_invoke (DBusGProxy        *proxy, +		     const char        *method, +		     const char        *insig, +		     const char        *outsig, +		     GError           **error, +		     ...) +{ +  DBusPendingCall *pending; +  DBusMessage *message; +  DBusMessage *reply; +  va_list args; +  va_list args_unwind; +  int n_retvals_processed; +  DBusMessageIter msgiter; +  DBusSignatureIter sigiter; +  int expected_type; +  gboolean ret; +  DBusError derror; +   +  g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE); +  g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE); + +  va_start (args, error); +  /* Keep around a copy of output arguments so we +   * can free on error. */ +  G_VA_COPY (args_unwind, args); + +  ret = FALSE; +  pending = NULL; +  reply = NULL; +  n_retvals_processed = 0; +  message = dbus_message_new_method_call (proxy->name, +                                          proxy->path, +                                          proxy->interface, +                                          method); +  if (message == NULL) +    goto oom; + +  dbus_signature_iter_init (&sigiter, insig); +  dbus_message_iter_init_append (message, &msgiter); +  while ((expected_type = dbus_signature_iter_get_current_type (&sigiter)) != DBUS_TYPE_INVALID) +    { +      GValue gvalue = {0, }; +      char *collect_err; + +      if (!dbus_gvalue_init (expected_type, &gvalue)) +	{ +	  g_set_error (error, DBUS_GERROR, +		       DBUS_GERROR_INVALID_ARGS, +		       _("Unsupported type '%c'"), expected_type); +	  goto out; +	}  +       +      G_VALUE_COLLECT (&gvalue, args, G_VALUE_NOCOPY_CONTENTS, &collect_err); + +      if (collect_err) +	{ +	  g_set_error (error, DBUS_GERROR, +		       DBUS_GERROR_INVALID_ARGS, +		       collect_err); +	  goto out; +	} + +      /* Anything we can init must be marshallable */ +      if (!dbus_gvalue_marshal (&msgiter, &gvalue)) +	g_assert_not_reached (); +      g_value_unset (&gvalue); + +      dbus_signature_iter_next (&sigiter); +    } + +  if (!dbus_connection_send_with_reply (proxy->manager->connection, +                                        message, +                                        &pending, +                                        -1)) +    goto oom; + +  dbus_pending_call_block (pending); +  reply = dbus_pending_call_steal_reply (pending); + +  g_assert (reply != NULL); + +  dbus_error_init (&derror); + +  switch (dbus_message_get_type (reply)) +    { +    case DBUS_MESSAGE_TYPE_METHOD_RETURN: + +      dbus_signature_iter_init (&sigiter, outsig); +      dbus_message_iter_init (reply, &msgiter); +      while ((expected_type = dbus_signature_iter_get_current_type (&sigiter)) != DBUS_TYPE_INVALID) +	{ +	  int arg_type; +	  gpointer *value_ret; +	  GValue gvalue = { 0, }; + +	  value_ret = va_arg (args, gpointer *); + +	  arg_type = dbus_message_iter_get_arg_type (&msgiter); +	  if (expected_type != arg_type) +	    { +	      if (arg_type == DBUS_TYPE_INVALID) +		  g_set_error (error, DBUS_GERROR, +			       DBUS_GERROR_INVALID_ARGS, +			       _("Too few arguments in reply")); +	      else +		  g_set_error (error, DBUS_GERROR, +			       DBUS_GERROR_INVALID_ARGS, +			       _("Reply argument was \"%c\", expected \"%c\""), +			       arg_type, expected_type);   +	      goto out; +	    } +	   +	  if (!dbus_gvalue_demarshal (&msgiter, &gvalue)) +	    { +	      g_set_error (error, +			   DBUS_GERROR, +			   DBUS_GERROR_INVALID_ARGS, +			   _("Couldn't convert argument type \"%c\""), expected_type); +	      goto out; +	    } +	  /* Anything that can be demarshaled must be storable */ +	  if (!dbus_gvalue_store (&gvalue, value_ret)) +	    g_assert_not_reached (); +	  g_value_unset (&gvalue); +	   +	  n_retvals_processed++; +	  dbus_signature_iter_next (&sigiter); +	  dbus_message_iter_next (&msgiter); +	} +      if (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID) +	{ +	  g_set_error (error, DBUS_GERROR, +		       DBUS_GERROR_INVALID_ARGS, +		       _("Too many arguments")); +	  goto out; +	} +      break; +    case DBUS_MESSAGE_TYPE_ERROR: +      dbus_set_error_from_message (&derror, reply); +      dbus_set_g_error (error, &derror); +      dbus_error_free (&derror); +      goto out; +      break; +    default: +      dbus_set_error (&derror, DBUS_ERROR_FAILED, +                      "Reply was neither a method return nor an exception"); +      dbus_set_g_error (error, &derror); +      dbus_error_free (&derror); +      goto out; +      break; +    } + +  ret = TRUE; + out: +  va_end (args); + +  if (ret == FALSE) +    { +      int i; +      for (i = 0; i < n_retvals_processed; i++) +	{ +	  gpointer retval; + +	  retval = va_arg (args_unwind, gpointer); + +	  g_free (retval); +	} +    } +  va_end (args_unwind); + +  if (pending) +    dbus_pending_call_unref (pending); +  if (message) +    dbus_message_unref (message); +  if (reply) +    dbus_message_unref (reply); +  return ret; + oom: +  g_error ("Out of memory"); +  ret = FALSE; +  goto out; +} + +/**   * Sends a method call message as with dbus_g_proxy_begin_call(), but   * does not ask for a reply or allow you to receive one.   * diff --git a/glib/dbus-gvalue.c b/glib/dbus-gvalue.c index bcda9259..eae5a458 100644 --- a/glib/dbus-gvalue.c +++ b/glib/dbus-gvalue.c @@ -26,50 +26,51 @@  #include "dbus/dbus-signature.h"  /* This is slightly evil, we don't use g_value_set_foo() functions */ -#define MAP_BASIC_INIT(d_t, g_t)                                     \ -    case DBUS_TYPE_##d_t:                                       \ -      g_value_init (value, G_TYPE_##g_t);                       \ -      break +#define MAP_BASIC(d_t, g_t)                     \ +    case DBUS_TYPE_##d_t:                       \ +      return G_TYPE_##g_t; -gboolean -dbus_gvalue_init      (int     type, -		       GValue *value) +static GType +dbus_dbus_type_to_gtype (int type)  { -  gboolean can_convert; - -  can_convert = TRUE; -    switch (type)      { -      MAP_BASIC_INIT (BOOLEAN, BOOLEAN); -      MAP_BASIC_INIT (BYTE,    UCHAR); -      MAP_BASIC_INIT (INT32,   INT); -      MAP_BASIC_INIT (UINT32,  UINT); -      MAP_BASIC_INIT (INT64,   INT64); -      MAP_BASIC_INIT (UINT64,  UINT64); -      MAP_BASIC_INIT (DOUBLE,  DOUBLE); - +      MAP_BASIC (BOOLEAN, BOOLEAN); +      MAP_BASIC (BYTE,    UCHAR); +      MAP_BASIC (INT32,   INT); +      MAP_BASIC (UINT32,  UINT); +      MAP_BASIC (INT64,   INT64); +      MAP_BASIC (UINT64,  UINT64); +      MAP_BASIC (DOUBLE,  DOUBLE);      case DBUS_TYPE_INT16: -        g_value_init (value, G_TYPE_INT); -      break; +      return G_TYPE_INT;      case DBUS_TYPE_UINT16: -        g_value_init (value, G_TYPE_UINT); -      break; -       +      return G_TYPE_UINT;      case DBUS_TYPE_STRING:      case DBUS_TYPE_OBJECT_PATH:      case DBUS_TYPE_SIGNATURE: -        g_value_init (value, G_TYPE_STRING); -      break; -       +      return G_TYPE_STRING;      case DBUS_TYPE_STRUCT:      case DBUS_TYPE_ARRAY:      case DBUS_TYPE_VARIANT:      default: -      can_convert = FALSE; +      return G_TYPE_INVALID;      } -#undef MAP_BASIC_INIT -  return can_convert; +} + +#undef MAP_BASIC + +gboolean +dbus_gvalue_init (int     type, +		  GValue *value) +{ +  GType gtype; + +  gtype = dbus_dbus_type_to_gtype (type); +  if (gtype == G_TYPE_INVALID) +    return FALSE; +  g_value_init (value, gtype); +  return TRUE;  }  /* FIXME - broken for containers @@ -125,43 +126,6 @@ dbus_gvalue_genmarshal_name_from_type (const char *signature)  }  const char * -dbus_gvalue_binding_type_from_type (const char *signature) -{ -  int type; - -  type = base_type_from_signature (signature); - -#define STRINGIFY(x) \ -  case x: \ -    return (#x) -   -  switch (type) -    { -      STRINGIFY(DBUS_TYPE_BOOLEAN); -      STRINGIFY(DBUS_TYPE_BYTE); -      STRINGIFY(DBUS_TYPE_INT32); -      STRINGIFY(DBUS_TYPE_UINT32); -      STRINGIFY(DBUS_TYPE_INT64); -      STRINGIFY(DBUS_TYPE_UINT64); -      STRINGIFY(DBUS_TYPE_DOUBLE); -    case DBUS_TYPE_INT16: -      return "DBUS_TYPE_INT32"; -    case DBUS_TYPE_UINT16: -      return "DBUS_TYPE_UINT32"; -    STRINGIFY(DBUS_TYPE_STRING); -    STRINGIFY(DBUS_TYPE_OBJECT_PATH); -    STRINGIFY(DBUS_TYPE_SIGNATURE); - -    case DBUS_TYPE_STRUCT: -    case DBUS_TYPE_ARRAY: -    case DBUS_TYPE_VARIANT: -      return NULL; -    } -#undef STRINGIFY -  return NULL; -} - -const char *  dbus_gvalue_ctype_from_type (const char *signature, gboolean in)  {    int type; @@ -249,69 +213,96 @@ dbus_gtype_to_dbus_type (GType type)  gboolean  dbus_gvalue_demarshal (DBusMessageIter *iter, GValue *value)  { -  gboolean can_convert = TRUE; -    g_assert (sizeof (dbus_bool_t) == sizeof (value->data[0].v_int));    dbus_gvalue_init (dbus_message_iter_get_arg_type (iter), value); -/* This is slightly evil, we don't use g_value_set_foo() functions */ -#define MAP_BASIC(d_t, g_t)                                     \ -    case DBUS_TYPE_##d_t:                                       \ -      dbus_message_iter_get_basic (iter, &value->data[0]);      \ -      break -    switch (dbus_message_iter_get_arg_type (iter))      { -      MAP_BASIC (BOOLEAN, BOOLEAN); -      MAP_BASIC (BYTE,    UCHAR); -      MAP_BASIC (INT32,   INT); -      MAP_BASIC (UINT32,  UINT); -      MAP_BASIC (INT64,   INT64); -      MAP_BASIC (UINT64,  UINT64); -      MAP_BASIC (DOUBLE,  DOUBLE); - +    case DBUS_TYPE_BOOLEAN: +      { +	dbus_bool_t bool; +	dbus_message_iter_get_basic (iter, &bool); +	g_value_set_boolean (value, bool); +	return TRUE; +      } +    case DBUS_TYPE_BYTE: +      { +	unsigned char byte; +	dbus_message_iter_get_basic (iter, &byte); +	g_value_set_uchar (value, byte); +	return TRUE; +      } +    case DBUS_TYPE_INT32: +      { +	dbus_int32_t intval; +	dbus_message_iter_get_basic (iter, &intval); +	g_value_set_int (value, intval); +	return TRUE; +      } +    case DBUS_TYPE_UINT32: +      { +	dbus_uint32_t intval; +	dbus_message_iter_get_basic (iter, &intval); +	g_value_set_uint (value, intval); +	return TRUE; +      } +    case DBUS_TYPE_INT64: +      { +	dbus_int64_t intval; +	dbus_message_iter_get_basic (iter, &intval); +	g_value_set_int64 (value, intval); +	return TRUE; +      } +    case DBUS_TYPE_UINT64: +      { +	dbus_uint64_t intval; +	dbus_message_iter_get_basic (iter, &intval); +	g_value_set_uint64 (value, intval); +	return TRUE; +      } +    case DBUS_TYPE_DOUBLE: +      { +	double dval; +	dbus_message_iter_get_basic (iter, &dval); +	g_value_set_double (value, dval); +	return TRUE; +      }      case DBUS_TYPE_INT16:        {          dbus_int16_t v;          dbus_message_iter_get_basic (iter, &v);          g_value_set_int (value, v); +	return TRUE;        } -      break;      case DBUS_TYPE_UINT16:        {          dbus_uint16_t v;          dbus_message_iter_get_basic (iter, &v);          g_value_set_uint (value, v); +	return TRUE;        } -      break; -            case DBUS_TYPE_STRING:      case DBUS_TYPE_OBJECT_PATH:      case DBUS_TYPE_SIGNATURE:        {          const char *s; -          dbus_message_iter_get_basic (iter, &s);          g_value_set_string (value, s); +	return TRUE;        } -      break; -            case DBUS_TYPE_STRUCT:      case DBUS_TYPE_ARRAY:      case DBUS_TYPE_VARIANT:      default: -      can_convert = FALSE; +      return FALSE;      } -#undef MAP_BASIC -  return can_convert;  }  gboolean  dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)  { -  gboolean can_convert = TRUE; -  GType value_type = G_VALUE_TYPE (value); +  GType value_type;    value_type = G_VALUE_TYPE (value); @@ -325,7 +316,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &b))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_UCHAR:        {          unsigned char b = g_value_get_uchar (value); @@ -334,7 +325,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &b))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_BOOLEAN:        {          dbus_bool_t b = g_value_get_boolean (value); @@ -343,7 +334,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &b))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_INT:        {          dbus_int32_t v = g_value_get_int (value); @@ -352,7 +343,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_UINT:        {          dbus_uint32_t v = g_value_get_uint (value); @@ -361,7 +352,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;        /* long gets cut to 32 bits so the remote API is consistent         * on all architectures         */ @@ -373,7 +364,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_ULONG:        {          dbus_uint32_t v = g_value_get_ulong (value); @@ -382,7 +373,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_INT64:        {          gint64 v = g_value_get_int64 (value); @@ -391,7 +382,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_UINT64:        {          guint64 v = g_value_get_uint64 (value); @@ -400,7 +391,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_FLOAT:        {          double v = g_value_get_float (value); @@ -410,7 +401,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_DOUBLE:        {          double v = g_value_get_double (value); @@ -420,7 +411,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      case G_TYPE_STRING:        /* FIXME, the GValue string may not be valid UTF-8 */        { @@ -430,19 +421,62 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)                                               &v))            goto nomem;        } -      break; +      return TRUE;      default:        /* FIXME: we need to define custom boxed types for arrays  	 etc. so we can map them transparently / pleasantly */ -      can_convert = FALSE; -      break; +      return FALSE;      } -  return can_convert; -   nomem:    g_error ("no memory");    return FALSE;  } +/* FIXME is there a better way to do this? */ +gboolean +dbus_gvalue_store (GValue          *value, +		   gpointer        storage) +{ +  switch (G_VALUE_TYPE (value)) +    { +    case G_TYPE_CHAR: +      *((gchar *) storage) = g_value_get_char (value); +      return TRUE; +    case G_TYPE_UCHAR: +      *((guchar *) storage) = g_value_get_uchar (value); +      return TRUE; +    case G_TYPE_BOOLEAN: +      *((gboolean *) storage) = g_value_get_boolean (value); +      return TRUE; +    case G_TYPE_LONG: +      *((glong *) storage) = g_value_get_long (value); +      return TRUE; +    case G_TYPE_ULONG: +      *((gulong *) storage) = g_value_get_ulong (value); +      return TRUE; +    case G_TYPE_INT: +      *((gint *) storage) = g_value_get_int (value); +      return TRUE; +    case G_TYPE_UINT: +      *((guint *) storage) = g_value_get_uint (value); +      return TRUE; +    case G_TYPE_INT64: +      *((gint64 *) storage) = g_value_get_int64 (value); +      return TRUE; +    case G_TYPE_UINT64: +      *((guint64 *) storage) = g_value_get_uint64 (value); +      return TRUE; +    case G_TYPE_FLOAT: +    case G_TYPE_DOUBLE: +      *((gdouble *) storage) = g_value_get_double (value); +      return TRUE; +    case G_TYPE_STRING: +      /* FIXME - should optimize by not duping string twice */ +      *((gchar **) storage) = g_value_dup_string (value); +      return TRUE; +    default: +      return FALSE; +    } +} diff --git a/glib/dbus-gvalue.h b/glib/dbus-gvalue.h index dc1cf323..4caa6880 100644 --- a/glib/dbus-gvalue.h +++ b/glib/dbus-gvalue.h @@ -24,8 +24,6 @@ const char *   dbus_gvalue_genmarshal_name_from_type (const char *type);  const char *   dbus_gvalue_ctype_from_type           (const char *type, gboolean in); -const char *   dbus_gvalue_binding_type_from_type    (const char *type); -  const char *   dbus_gtype_to_dbus_type    (GType            type);  gboolean       dbus_gvalue_init           (int              type, @@ -36,6 +34,8 @@ gboolean       dbus_gvalue_demarshal      (DBusMessageIter *iter,  gboolean       dbus_gvalue_marshal        (DBusMessageIter *iter,  					   GValue          *value); +gboolean       dbus_gvalue_store          (GValue          *value, +					   gpointer         storage);  G_END_DECLS diff --git a/test/glib/Makefile.am b/test/glib/Makefile.am index 58f4d778..b0b8361a 100644 --- a/test/glib/Makefile.am +++ b/test/glib/Makefile.am @@ -44,10 +44,10 @@ test_service_glib_SOURCES=				\  BUILT_SOURCES = test-service-glib-glue.h test-service-glib-bindings.h -test-service-glib-glue.h: test-service-glib.xml +test-service-glib-glue.h: test-service-glib.xml $(top_builddir)/glib/dbus-binding-tool  	$(top_builddir)/glib/dbus-binding-tool --mode=glib-server --output=test-service-glib-glue.h test-service-glib.xml -test-service-glib-bindings.h: test-service-glib.xml +test-service-glib-bindings.h: test-service-glib.xml $(top_builddir)/glib/dbus-binding-tool  	$(top_builddir)/glib/dbus-binding-tool --mode=glib-client --output=test-service-glib-bindings.h test-service-glib.xml  CLEANFILES = test-service-glib-glue.h test-service-glib-bindings.h diff --git a/test/glib/test-dbus-glib.c b/test/glib/test-dbus-glib.c index 0c2078e5..b0dc9efc 100644 --- a/test/glib/test-dbus-glib.c +++ b/test/glib/test-dbus-glib.c @@ -267,7 +267,7 @@ main (int argc, char **argv)      lose ("ThrowError call unexpectedly succeeded!");    g_print ("ThrowError failed (as expected) returned error: %s\n", error->message); -  g_error_free (error); +  g_clear_error (&error);    v_STRING = "foobar";    call = dbus_g_proxy_begin_call (proxy, "Uppercase", @@ -313,12 +313,13 @@ main (int argc, char **argv)      lose ("(wrapped) ThrowError call unexpectedly succeeded!");    g_print ("(wrapped) ThrowError failed (as expected) returned error: %s\n", error->message); -  g_error_free (error); +  g_clear_error (&error);    if (!org_freedesktop_DBus_Tests_MyObject_uppercase (proxy, "foobar", &v_STRING_2, &error))       lose_gerror ("Failed to complete (wrapped) Uppercase call", error);    if (strcmp ("FOOBAR", v_STRING_2) != 0)      lose ("(wrapped) Uppercase call returned unexpected string %s", v_STRING_2); +  g_free (v_STRING_2);    if (!org_freedesktop_DBus_Tests_MyObject_many_args (proxy, 26, "bazwhee", G_PI,  						      &v_DOUBLE_2, &v_STRING_2, &error)) @@ -330,6 +331,7 @@ main (int argc, char **argv)    if (strcmp ("BAZWHEE", v_STRING_2) != 0)      lose ("(wrapped) ManyArgs call returned unexpected string %s", v_STRING_2); +  g_free (v_STRING_2);    g_object_unref (G_OBJECT (proxy)); | 
