summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2005-03-09 17:09:11 +0000
committerColin Walters <walters@verbum.org>2005-03-09 17:09:11 +0000
commit74b1b35402f6b9bbc09999a6224dfc04bc48b2a9 (patch)
treec9cae2dde5d4b11d4cf7e17e5c3009280e1f8ee5
parent2958e723fc996e2dd7edfdc6ac53dcdf48323549 (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--ChangeLog55
-rw-r--r--dbus/dbus-glib.h7
-rw-r--r--dbus/dbus-marshal-basic.c34
-rw-r--r--dbus/dbus-marshal-byteswap.c3
-rw-r--r--dbus/dbus-marshal-recursive-util.c4
-rw-r--r--dbus/dbus-marshal-recursive.c8
-rw-r--r--dbus/dbus-message.c11
-rw-r--r--dbus/dbus-signature.c30
-rw-r--r--dbus/dbus-signature.h1
-rw-r--r--glib/dbus-binding-tool-glib.c73
-rw-r--r--glib/dbus-gproxy.c205
-rw-r--r--glib/dbus-gvalue.c254
-rw-r--r--glib/dbus-gvalue.h4
-rw-r--r--test/glib/Makefile.am4
-rw-r--r--test/glib/test-dbus-glib.c6
15 files changed, 509 insertions, 190 deletions
diff --git a/ChangeLog b/ChangeLog
index 844b73ca..c57228a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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));