summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-06-16 13:53:36 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-06-16 13:53:36 -0400
commitca054efa1b317a219b2b83652c16e6017b789f30 (patch)
treee27d2d0f5506933be9cd81694905549a25c0bdb3
parent917e0632cb4e8a4508112075b48a608ac36f8c33 (diff)
Updates
-rw-r--r--src/gdbusgi.c1482
-rw-r--r--src/myfrobnicator.c54
-rw-r--r--src/myfrobnicator.h8
-rw-r--r--src/test.c33
4 files changed, 1124 insertions, 453 deletions
diff --git a/src/gdbusgi.c b/src/gdbusgi.c
index 1578d6d..138e00d 100644
--- a/src/gdbusgi.c
+++ b/src/gdbusgi.c
@@ -23,6 +23,632 @@
#include <girepository.h>
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GVariantType *
+get_gvariant_type_for_gi_type (GITypeInfo *gi_type,
+ const GVariantType *requested_gvariant_type, /* may be NULL */
+ GError **error)
+{
+ GITypeTag tag;
+ GVariantType *gvariant_type;
+
+ g_return_val_if_fail (gi_type != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ gvariant_type = NULL;
+
+ tag = g_type_info_get_tag (gi_type);
+ switch (tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ gvariant_type = g_variant_type_new ("b");
+ break;
+
+ case GI_TYPE_TAG_INT8:
+ gvariant_type = g_variant_type_new ("y");
+ break;
+
+ case GI_TYPE_TAG_UINT8:
+ gvariant_type = g_variant_type_new ("y");
+ break;
+
+ case GI_TYPE_TAG_INT16:
+ gvariant_type = g_variant_type_new ("n");
+ break;
+
+ case GI_TYPE_TAG_UINT16:
+ gvariant_type = g_variant_type_new ("q");
+ break;
+
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_INT32:
+ gvariant_type = g_variant_type_new ("i");
+ break;
+
+ case GI_TYPE_TAG_UINT:
+ case GI_TYPE_TAG_UINT32:
+ gvariant_type = g_variant_type_new ("u");
+ break;
+
+ case GI_TYPE_TAG_INT64:
+ gvariant_type = g_variant_type_new ("x");
+ break;
+
+ case GI_TYPE_TAG_UINT64:
+ gvariant_type = g_variant_type_new ("t");
+ break;
+
+ case GI_TYPE_TAG_DOUBLE:
+ gvariant_type = g_variant_type_new ("d");
+ break;
+
+ case GI_TYPE_TAG_UTF8:
+ if (requested_gvariant_type != NULL &&
+ (g_variant_type_equal (requested_gvariant_type, G_VARIANT_TYPE_STRING) ||
+ g_variant_type_equal (requested_gvariant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
+ g_variant_type_equal (requested_gvariant_type, G_VARIANT_TYPE_SIGNATURE)))
+ gvariant_type = g_variant_type_copy (requested_gvariant_type);
+ else
+ gvariant_type = g_variant_type_new ("s");
+ break;
+
+ case GI_TYPE_TAG_ARRAY:
+ {
+ const GVariantType *element_requested_gvariant_type;
+ GITypeInfo *element_type;
+ GVariantType *element_gvariant_type;
+ GITypeTag element_type_tag;
+
+ element_requested_gvariant_type = NULL;
+ if (requested_gvariant_type != NULL)
+ {
+ if (!g_variant_type_is_array (requested_gvariant_type))
+ {
+ gchar *s;
+ s = g_variant_type_dup_string (requested_gvariant_type);
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Type tag GI_TYPE_ARRAY requires an signature starting with `a' but the "
+ "requested signature is `%s'",
+ s);
+ g_free (s);
+ goto out;
+ }
+ element_requested_gvariant_type = g_variant_type_element (requested_gvariant_type);
+ }
+
+ element_type = g_type_info_get_param_type (gi_type, 0);
+ element_type_tag = g_type_info_get_tag (element_type);
+ element_gvariant_type = get_gvariant_type_for_gi_type (element_type,
+ element_requested_gvariant_type,
+ error);
+ g_base_info_unref ((GIBaseInfo *) element_type);
+ if (element_gvariant_type == NULL)
+ goto out;
+
+ switch (g_type_info_get_array_type (gi_type))
+ {
+ case GI_ARRAY_TYPE_C:
+ switch (element_type_tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
+ case GI_TYPE_TAG_DOUBLE:
+ case GI_TYPE_TAG_UTF8:
+ /* ^^^ Only these types are OK */
+
+ /* However, we only support zero-terminated for strings */
+ if (element_type_tag != GI_TYPE_TAG_UTF8 && g_type_info_is_zero_terminated (gi_type))
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Element type `%s' in C array can't be used with zero-terminated",
+ g_type_tag_to_string (element_type_tag));
+ goto out;
+ }
+ break;
+
+ default:
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unsupported element type `%s' in C array",
+ g_type_tag_to_string (element_type_tag));
+ goto out;
+ }
+
+ break;
+
+ case GI_ARRAY_TYPE_ARRAY:
+ switch (element_type_tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
+ case GI_TYPE_TAG_DOUBLE:
+ /* ^^^ Only these types are OK */
+ break;
+
+ default:
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unsupported element type `%s' in GArray array (only scalar types are supported)",
+ g_type_tag_to_string (element_type_tag));
+ goto out;
+ }
+ break;
+
+ case GI_ARRAY_TYPE_PTR_ARRAY:
+ switch (element_type_tag)
+ {
+ case GI_TYPE_TAG_UTF8:
+ /* ^^^ Only this type is OK */
+ break;
+
+ default:
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unsupported element type `%s' in GPtrArray array",
+ g_type_tag_to_string (element_type_tag));
+ goto out;
+ }
+ break;
+
+ case GI_ARRAY_TYPE_BYTE_ARRAY:
+ switch (element_type_tag)
+ {
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ /* ^^^ Only these types are OK */
+ break;
+
+ default:
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unsupported element type `%s' in GByteArray array",
+ g_type_tag_to_string (element_type_tag));
+ goto out;
+ }
+ break;
+ break;
+ }
+ gvariant_type = g_variant_type_new_array (element_gvariant_type);
+ g_variant_type_free (element_gvariant_type);
+ }
+ break;
+
+ default:
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Type tag `%s' not supported",
+ g_type_tag_to_string (tag));
+ goto out;
+ }
+
+ if (gvariant_type != NULL)
+ {
+ if (requested_gvariant_type != NULL && !g_variant_type_equal (gvariant_type, requested_gvariant_type))
+ {
+ gchar *s;
+ gchar *s2;
+ s = g_variant_type_dup_string (gvariant_type);
+ s2 = g_variant_type_dup_string (requested_gvariant_type);
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Type tag `%s' defaults to D-Bus signature `%s' which is incompatible with requested signature `%s'",
+ g_type_tag_to_string (tag),
+ s,
+ s2);
+ g_free (s);
+ g_free (s2);
+ g_variant_type_free (gvariant_type);
+ gvariant_type = NULL;
+ goto out;
+ }
+ }
+
+ out:
+ return gvariant_type;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GVariant *
+convert_gi_to_gvariant (GArgument *gi_value,
+ GITypeInfo *gi_type,
+ const GVariantType *expected_gvariant_type) /* may be NULL */
+{
+ GVariant *ret;
+ GITypeTag tag;
+
+ g_return_val_if_fail (gi_value != NULL, NULL);
+ g_return_val_if_fail (gi_type != NULL, NULL);
+
+ ret = NULL;
+ tag = g_type_info_get_tag (gi_type);
+
+ switch (tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_BOOLEAN));
+ ret = g_variant_new_boolean (gi_value->v_boolean);
+ break;
+
+ case GI_TYPE_TAG_INT8:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_BYTE));
+ ret = g_variant_new_byte (gi_value->v_int8);
+ break;
+
+ case GI_TYPE_TAG_UINT8:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_BYTE));
+ ret = g_variant_new_byte (gi_value->v_uint8);
+ break;
+
+ case GI_TYPE_TAG_INT16:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_INT16));
+ ret = g_variant_new_int16 (gi_value->v_int16);
+ break;
+
+ case GI_TYPE_TAG_UINT16:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_UINT16));
+ ret = g_variant_new_uint16 (gi_value->v_uint16);
+ break;
+
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_INT32:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_INT32));
+ ret = g_variant_new_int32 (gi_value->v_int32);
+ break;
+
+ case GI_TYPE_TAG_UINT:
+ case GI_TYPE_TAG_UINT32:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_UINT32));
+ ret = g_variant_new_uint32 (gi_value->v_uint32);
+ break;
+
+ case GI_TYPE_TAG_INT64:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_INT64));
+ ret = g_variant_new_int64 (gi_value->v_int64);
+ break;
+
+ case GI_TYPE_TAG_UINT64:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_UINT64));
+ ret = g_variant_new_uint64 (gi_value->v_uint64);
+ break;
+
+ case GI_TYPE_TAG_DOUBLE:
+ g_assert (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_DOUBLE));
+ ret = g_variant_new_double (gi_value->v_double);
+ break;
+
+ case GI_TYPE_TAG_UTF8:
+ if (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_STRING))
+ {
+ ret = g_variant_new_string (gi_value->v_string);
+ }
+ else if (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_OBJECT_PATH))
+ {
+ ret = g_variant_new_object_path (gi_value->v_string);
+ }
+ else if (g_variant_type_equal (expected_gvariant_type, G_VARIANT_TYPE_SIGNATURE))
+ {
+ ret = g_variant_new_signature (gi_value->v_string);
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* g_error()'s if type is not a scalar type */
+static guint
+get_scalar_element_size (GITypeInfo *type)
+{
+ GITypeTag tag;
+ guint ret;
+
+ ret = 0;
+
+ tag = g_type_info_get_tag (type);
+ switch (tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ ret = sizeof (gboolean);
+ break;
+
+ case GI_TYPE_TAG_INT8:
+ ret = sizeof (gint8);
+ break;
+
+ case GI_TYPE_TAG_UINT8:
+ ret = sizeof (guint8);
+ break;
+
+ case GI_TYPE_TAG_INT16:
+ ret = sizeof (gint16);
+ break;
+
+ case GI_TYPE_TAG_UINT16:
+ ret = sizeof (guint16);
+ break;
+
+ case GI_TYPE_TAG_INT32:
+ ret = sizeof (gint32);
+ break;
+
+ case GI_TYPE_TAG_UINT32:
+ ret = sizeof (guint32);
+ break;
+
+ case GI_TYPE_TAG_INT64:
+ ret = sizeof (gint64);
+ break;
+
+ case GI_TYPE_TAG_UINT64:
+ ret = sizeof (guint64);
+ break;
+
+ case GI_TYPE_TAG_INT:
+ ret = sizeof (gint);
+ break;
+
+ case GI_TYPE_TAG_UINT:
+ ret = sizeof (guint);
+ break;
+
+ case GI_TYPE_TAG_DOUBLE:
+ ret = sizeof (gdouble);
+ break;
+
+ default:
+ g_error ("Type with tag `%s' is not a scalar type", g_type_tag_to_string (tag));
+ break;
+ }
+
+ return ret;
+}
+
+static void
+convert_gvariant_to_gi (GVariant *variant,
+ GArgument *out_gi_value,
+ GITypeInfo *gi_type,
+ GITransfer transfer)
+{
+ GITypeTag tag;
+ const GVariantType *gvariant_type;
+
+ g_return_if_fail (variant != NULL);
+ g_return_if_fail (out_gi_value != NULL);
+ g_return_if_fail (gi_type != NULL);
+
+ gvariant_type = g_variant_get_type (variant);
+ tag = g_type_info_get_tag (gi_type);
+
+ switch (tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_BOOLEAN));
+ out_gi_value->v_boolean = g_variant_get_boolean (variant);
+ break;
+
+ case GI_TYPE_TAG_INT8:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_BYTE));
+ out_gi_value->v_int8 = g_variant_get_byte (variant);
+ break;
+
+ case GI_TYPE_TAG_UINT8:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_BYTE));
+ out_gi_value->v_uint8 = g_variant_get_byte (variant);
+ break;
+
+ case GI_TYPE_TAG_INT16:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_INT16));
+ out_gi_value->v_int16 = g_variant_get_int16 (variant);
+ break;
+
+ case GI_TYPE_TAG_UINT16:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_UINT16));
+ out_gi_value->v_uint16 = g_variant_get_uint16 (variant);
+ break;
+
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_INT32:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_INT32));
+ out_gi_value->v_int32 = g_variant_get_int32 (variant);
+ break;
+
+ case GI_TYPE_TAG_UINT:
+ case GI_TYPE_TAG_UINT32:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_UINT32));
+ out_gi_value->v_uint32 = g_variant_get_uint32 (variant);
+ break;
+
+ case GI_TYPE_TAG_INT64:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_INT64));
+ out_gi_value->v_int64 = g_variant_get_int64 (variant);
+ break;
+
+ case GI_TYPE_TAG_UINT64:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_UINT64));
+ out_gi_value->v_uint64 = g_variant_get_uint64 (variant);
+ break;
+
+ case GI_TYPE_TAG_DOUBLE:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_DOUBLE));
+ out_gi_value->v_double = g_variant_get_double (variant);
+ break;
+
+ case GI_TYPE_TAG_UTF8:
+ g_assert (g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_STRING) ||
+ g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
+ g_variant_type_equal (gvariant_type, G_VARIANT_TYPE_SIGNATURE));
+ switch (transfer)
+ {
+ case GI_TRANSFER_NOTHING:
+ out_gi_value->v_string = (gchar *) g_variant_get_string (variant, NULL);
+ break;
+ case GI_TRANSFER_CONTAINER:
+ g_assert_not_reached ();
+ break;
+ case GI_TRANSFER_EVERYTHING:
+ out_gi_value->v_string = g_variant_dup_string (variant, NULL);
+ break;
+ }
+ break;
+
+ case GI_TYPE_TAG_ARRAY:
+ {
+ GITypeInfo *element_type;
+ GITransfer element_transfer;
+ GVariantIter iter;
+ guint num_elems;
+ guint n;
+
+ g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_ARRAY));
+
+ element_type = g_type_info_get_param_type (gi_type, 0);
+
+ element_transfer = GI_TRANSFER_NOTHING;
+ if (transfer == GI_TRANSFER_EVERYTHING)
+ element_transfer = GI_TRANSFER_EVERYTHING;
+
+ num_elems = g_variant_n_children (variant);
+
+ switch (g_type_info_get_array_type (gi_type))
+ {
+ case GI_ARRAY_TYPE_C:
+ {
+#if 0
+ g_print ("fixed_size=%d array_length=%d zero_terminated=%d\n",
+ g_type_info_get_array_fixed_size (gi_type),
+ g_type_info_get_array_length (gi_type),
+ g_type_info_is_zero_terminated (gi_type));
+#endif
+
+ if (g_type_info_is_zero_terminated (gi_type))
+ {
+ gpointer *p;
+ p = g_new0 (gpointer, num_elems + 1);
+ g_variant_iter_init (&iter, variant);
+ for (n = 0; n < num_elems; n++)
+ {
+ GArgument a = {0};
+ GVariant *item;
+ item = g_variant_iter_next_value (&iter);
+ g_assert (item != NULL);
+ convert_gvariant_to_gi (item,
+ &a,
+ element_type,
+ element_transfer);
+ p[n] = a.v_pointer;
+ }
+ out_gi_value->v_pointer = p;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+ }
+ break;
+
+ case GI_ARRAY_TYPE_BYTE_ARRAY:
+ /* Explicit fallthrough: A GByteArray is really just a GArray */
+ case GI_ARRAY_TYPE_ARRAY:
+ {
+ GArray *p;
+ p = g_array_sized_new (FALSE, /* zero_terminated */
+ FALSE, /* clear_ */
+ get_scalar_element_size (element_type),
+ num_elems);
+ g_variant_iter_init (&iter, variant);
+ for (n = 0; n < num_elems; n++)
+ {
+ GArgument a = {0};
+ GVariant *item;
+
+ item = g_variant_iter_next_value (&iter);
+ g_assert (item != NULL);
+ convert_gvariant_to_gi (item,
+ &a,
+ element_type,
+ element_transfer);
+ g_array_append_vals (p, &a, 1);
+ }
+ out_gi_value->v_pointer = p;
+ }
+ break;
+
+ case GI_ARRAY_TYPE_PTR_ARRAY:
+ {
+ GPtrArray *p;
+ p = g_ptr_array_sized_new (num_elems);
+ g_variant_iter_init (&iter, variant);
+ for (n = 0; n < num_elems; n++)
+ {
+ GArgument a = {0};
+ GVariant *item;
+
+ item = g_variant_iter_next_value (&iter);
+ g_assert (item != NULL);
+ convert_gvariant_to_gi (item,
+ &a,
+ element_type,
+ element_transfer);
+ g_ptr_array_add (p, a.v_pointer);
+ }
+ out_gi_value->v_pointer = p;
+ }
+ break;
+ }
+ g_base_info_unref ((GIBaseInfo *) element_type);
+ }
+ break;
+
+ default:
+ g_error ("Don't know how to convert GVariant with type-string `%s' to type tag `%s'",
+ g_variant_get_type_string (variant),
+ g_type_tag_to_string (tag));
+ break;
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
typedef struct
{
GObject *object;
@@ -48,298 +674,252 @@ export_data_free (ExportData *data)
typedef struct
{
+ /* may be NULL for e.g. this/self or if the param is not exported via D-Bus (e.g. array length) */
+ GDBusArgInfo *dbus_arg_info;
+
+ /* may be NULL for self/this or for the return value */
+ GIArgInfo *arg_info;
+
+ /* is NULL only for this/self */
+ GITypeInfo *type_info;
+ GITransfer transfer;
+
+ /* these are -1 if not set */
+ gint array_len_position;
+ gint is_array_len_for_position;
+ gint inout_in_arg_offset;
+} ArgData;
+
+static ArgData *
+arg_data_new (void)
+{
+ ArgData *data;
+ data = g_new0 (ArgData, 1);
+ data->array_len_position = -1;
+ data->is_array_len_for_position = -1;
+ data->inout_in_arg_offset = -1;
+ return data;
+}
+
+static ArgData *
+arg_data_dup_without_dbus_arg_info (ArgData *data)
+{
+ ArgData *copy;
+ copy = g_memdup (data, sizeof (ArgData));
+ if (copy->arg_info != NULL)
+ g_base_info_ref ((GIBaseInfo *) copy->arg_info);
+ if (copy->type_info != NULL)
+ g_base_info_ref ((GIBaseInfo *) copy->type_info);
+ return copy;
+}
+
+static void
+arg_data_free (ArgData *data)
+{
+ if (data->dbus_arg_info != NULL)
+ g_dbus_arg_info_unref (data->dbus_arg_info);
+ if (data->arg_info != NULL)
+ g_base_info_unref ((GIBaseInfo *) data->arg_info);
+ if (data->type_info != NULL)
+ g_base_info_unref ((GIBaseInfo *) data->type_info);
+ g_free (data);
+}
+
+typedef struct
+{
GIFunctionInfo *method;
GDBusMethodInfo *dbus_method;
- guint num_gi_in_args;
- guint num_gi_out_args;
+
+ /* The following ArgData* correspond exactly to what g_function_info_invoke() requires */
+ GPtrArray *in_args;
+ GPtrArray *out_args;
+ ArgData *return_value;
} MethodData;
static void
method_data_free (MethodData *data)
{
g_base_info_unref (data->method);
- g_dbus_method_info_unref (data->dbus_method);
+ if (data->dbus_method != NULL)
+ g_dbus_method_info_unref (data->dbus_method);
+ g_ptr_array_unref (data->in_args);
+ g_ptr_array_unref (data->out_args);
+ if (data->return_value != NULL)
+ arg_data_free (data->return_value);
g_free (data);
}
/* ---------------------------------------------------------------------------------------------------- */
-static void
-set_in_arg (GVariant *value,
- GArgument *arg_to_set,
- GIArgInfo *arg_info)
+static gchar *
+arg_data_print (ArgData *data)
{
- const GVariantType *variant_type;
-
- variant_type = g_variant_get_type (value);
-
- if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN))
- arg_to_set->v_boolean = g_variant_get_boolean (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE))
- arg_to_set->v_int8 = g_variant_get_byte (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16))
- arg_to_set->v_int16 = g_variant_get_int16 (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16))
- arg_to_set->v_uint16 = g_variant_get_uint16 (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32))
- arg_to_set->v_int32 = g_variant_get_int32 (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32))
- arg_to_set->v_uint32 = g_variant_get_uint32 (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64))
- arg_to_set->v_int64 = g_variant_get_int64 (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64))
- arg_to_set->v_uint64 = g_variant_get_uint64 (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE))
- arg_to_set->v_double = g_variant_get_double (value);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING) ||
- g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH) ||
- g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE))
- {
- switch (g_arg_info_get_ownership_transfer (arg_info))
- {
- case GI_TRANSFER_NOTHING:
- arg_to_set->v_string = (gchar *) g_variant_get_string (value, NULL);
- break;
- case GI_TRANSFER_CONTAINER:
- g_assert_not_reached ();
- break;
- case GI_TRANSFER_EVERYTHING:
- arg_to_set->v_string = g_variant_dup_string (value, NULL);
- break;
- }
- }
- else
- {
- g_error ("Don't know how to set GVariant with type-string %s on a GArgument",
- g_variant_get_type_string (value));
- }
-}
+ GString *str;
+ str = g_string_new (NULL);
-static void
-prepare_in_args (GVariant *parameters,
- GArgument *in_args,
- guint num_in_args,
- GIFunctionInfo *method)
-{
- GVariantIter iter;
- GICallableInfo *callable;
- guint count_in_args;
- guint count_out_args;
- guint n;
+ g_string_append_printf (str,
+ "alp=%02d ialfp=%02d ioiao=%02d ",
+ data->array_len_position,
+ data->is_array_len_for_position,
+ data->inout_in_arg_offset);
- g_assert_cmpint (g_variant_n_children (parameters), ==, num_in_args);
-
- callable = (GICallableInfo *) method;
+ if (data->arg_info == NULL)
+ g_string_append (str, "name=(none)");
+ else
+ g_string_append_printf (str, "name=%s", g_base_info_get_name ((GIBaseInfo *) data->arg_info));
- count_in_args = 0;
- count_out_args = 0;
- g_variant_iter_init (&iter, parameters);
- for (n = 0; n < (guint) g_callable_info_get_n_args (callable); n++)
- {
- GArgument *arg_to_set;
- GIArgInfo *arg;
- GIDirection direction;
+ if (data->type_info == NULL)
+ g_string_append (str, " type=(none)");
+ else
+ g_string_append_printf (str, " type=%s", g_type_tag_to_string (g_type_info_get_tag (data->type_info)));
- arg = g_callable_info_get_arg (callable, n);
- direction = g_arg_info_get_direction (arg);
- arg_to_set = NULL;
- switch (direction)
- {
- case GI_DIRECTION_IN:
- arg_to_set = &in_args[count_in_args++];
- break;
+ if (data->dbus_arg_info == NULL)
+ g_string_append (str, " sig=(none)");
+ else
+ g_string_append_printf (str, " sig=%s", data->dbus_arg_info->signature);
- case GI_DIRECTION_OUT:
- /* do nothing */
- count_out_args++;
- break;
+ return g_string_free (str, FALSE);
+}
- case GI_DIRECTION_INOUT:
- count_out_args++;
- arg_to_set = &in_args[count_in_args++];
- break;
- }
+static gchar *
+method_data_print (MethodData *data,
+ guint indent)
+{
+ GString *str;
+ guint n;
+ gchar *s;
+
+ str = g_string_new (NULL);
+ g_string_append_printf (str,
+ "%*sSymbol: %s\n"
+ "%*sD-Bus name: %s\n",
+ indent, "", g_function_info_get_symbol (data->method),
+ indent, "", data->dbus_method->name);
+ for (n = 0; n < data->in_args->len; n++)
+ {
+ ArgData *a = data->in_args->pdata[n];
+ s = arg_data_print (a);
+ g_string_append_printf (str,
+ "%*s in_arg[%02d]: %s\n",
+ indent, "", n, s);
+ g_free (s);
+ }
+ for (n = 0; n < data->out_args->len; n++)
+ {
+ ArgData *a = data->out_args->pdata[n];
+ s = arg_data_print (a);
+ g_string_append_printf (str,
+ "%*s out_arg[%02d]: %s\n",
+ indent, "", n, s);
+ g_free (s);
+ }
- if (arg_to_set != NULL)
- {
- GVariant *item;
+ s = arg_data_print (data->return_value);
+ g_string_append_printf (str,
+ "%*s return value: %s\n",
+ indent, "", s);
+ g_free (s);
- item = g_variant_iter_next_value (&iter);
- g_assert (item != NULL);
- set_in_arg (item, arg_to_set, arg);
- }
- }
- g_assert_cmpint (count_in_args, ==, num_in_args);
+ return g_string_free (str, FALSE);
}
-/* ---------------------------------------------------------------------------------------------------- */
-
static void
-add_out_arg (GVariantBuilder *builder,
- GITypeInfo *type,
- GArgument *value,
- GDBusArgInfo *arg_info)
+method_data_dump (MethodData *data,
+ guint indent)
{
- const GVariantType *variant_type;
- GVariant *variant;
-
- variant_type = G_VARIANT_TYPE (arg_info->signature);
-
- if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN))
- variant = g_variant_new_boolean (value->v_boolean);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BYTE))
- variant = g_variant_new_byte (value->v_uint8);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT16))
- variant = g_variant_new_int16 (value->v_int16);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT16))
- variant = g_variant_new_uint16 (value->v_uint16);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32))
- variant = g_variant_new_int32 (value->v_int32);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32))
- variant = g_variant_new_uint32 (value->v_uint32);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64))
- variant = g_variant_new_int64 (value->v_int64);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT64))
- variant = g_variant_new_uint64 (value->v_uint64);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_DOUBLE))
- variant = g_variant_new_double (value->v_double);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING))
- variant = g_variant_new_string (value->v_string);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_OBJECT_PATH))
- variant = g_variant_new_object_path (value->v_string);
- else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE))
- variant = g_variant_new_signature (value->v_string);
- else
- g_assert_not_reached ();
-
- g_variant_builder_add_value (builder, variant);
+ gchar *s;
+ s = method_data_print (data, indent);
+ g_print ("------------------------------------------------------------------------\n"
+ "%s"
+ "------------------------------------------------------------------------\n",
+ s);
+ g_free (s);
}
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
-prepare_out_args (GArgument *return_value,
- GArgument *args,
- GArgument *arg_values,
- guint num_args,
- GIFunctionInfo *method,
- GDBusMethodInfo *dbus_method)
+prepare_args (GVariant *parameters,
+ GArgument *in_args,
+ GArgument *out_args,
+ GArgument *out_arg_values,
+ MethodData *data)
{
- GICallableInfo *callable;
guint n;
- guint count_out_args;
-
- callable = (GICallableInfo *) method;
+ GVariantIter iter;
- count_out_args = 0;
- for (n = 0; n < (guint) g_callable_info_get_n_args (callable); n++)
+ g_variant_iter_init (&iter, parameters);
+ for (n = 0; n < data->in_args->len; n++)
{
- GIArgInfo *arg;
- GIDirection direction;
+ ArgData *ad;
+ GVariant *item;
- arg = g_callable_info_get_arg (callable, n);
- direction = g_arg_info_get_direction (arg);
+ ad = data->in_args->pdata[n];
+ if (ad->dbus_arg_info == NULL)
+ continue;
- switch (direction)
- {
- case GI_DIRECTION_IN:
- /* do nothing */
- break;
+ item = g_variant_iter_next_value (&iter);
+ g_assert (item != NULL);
- case GI_DIRECTION_OUT:
- args[count_out_args].v_pointer = &arg_values[count_out_args];
- count_out_args++;
- break;
+ convert_gvariant_to_gi (item,
+ &in_args[n],
+ ad->type_info,
+ ad->transfer);
+ }
+ g_assert (g_variant_iter_next_value (&iter) == NULL);
- case GI_DIRECTION_INOUT:
- /* won't be used but needs to be present */
- args[count_out_args].v_pointer = NULL;
- count_out_args++;
- break;
- }
- g_base_info_unref ((GIBaseInfo *) arg);
+ for (n = 0; n < data->out_args->len; n++)
+ {
+ ArgData *ad;
+
+ ad = data->out_args->pdata[n];
+ if (ad->inout_in_arg_offset != -1)
+ out_args[n].v_pointer = &in_args[ad->inout_in_arg_offset];
+ else
+ out_args[n].v_pointer = &out_arg_values[n];
}
- g_assert_cmpint (num_args, ==, count_out_args);
}
+/* ---------------------------------------------------------------------------------------------------- */
+
static GVariant *
-process_out_args (GArgument *return_value,
- GArgument *in_args,
- GArgument *args,
- guint num_args,
- GIFunctionInfo *method,
- GDBusMethodInfo *dbus_method)
+process_args (GArgument *return_value,
+ GArgument *in_args,
+ GArgument *out_args,
+ MethodData *data)
{
- GVariant *ret;
- GVariantBuilder builder;
- GICallableInfo *callable;
- GITypeInfo *return_type;
- guint dbus_arg_num;
guint n;
- guint count_in_args;
- guint count_out_args;
-
- callable = (GICallableInfo *) method;
+ ArgData *ad;
+ GVariant *value;
+ GVariantType *gvariant_type;
+ GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
- dbus_arg_num = 0;
- return_type = g_callable_info_get_return_type (callable);
- if (g_type_info_get_tag (return_type) != GI_TYPE_TAG_VOID)
+ if (g_type_info_get_tag (data->return_value->type_info) != GI_TYPE_TAG_VOID)
{
- add_out_arg (&builder,
- return_type,
- return_value,
- dbus_method->out_args[dbus_arg_num++]);
+ ad = data->return_value;
+ gvariant_type = g_variant_type_new (ad->dbus_arg_info->signature);
+ value = convert_gi_to_gvariant (return_value,
+ ad->type_info,
+ gvariant_type);
+ g_variant_builder_add_value (&builder, value);
+ g_variant_type_free (gvariant_type);
}
- //g_base_info_unref ((GIBaseInfo *) return_type);
- count_in_args = 0;
- count_out_args = 0;
- for (n = 0; n < (guint) g_callable_info_get_n_args (callable); n++)
+ for (n = 0; n < data->out_args->len; n++)
{
- GIArgInfo *arg;
- GIDirection direction;
- GArgument *arg_with_value;
-
- arg = g_callable_info_get_arg (callable, n);
- direction = g_arg_info_get_direction (arg);
-
- arg_with_value = NULL;
- switch (direction)
- {
- case GI_DIRECTION_IN:
- /* do nothing */
- count_in_args++;
- break;
-
- case GI_DIRECTION_OUT:
- arg_with_value = args[count_out_args].v_pointer;
- count_out_args++;
- break;
-
- case GI_DIRECTION_INOUT:
- /* return value is in the in GArgument, not the out one (that needs to be present) */
- arg_with_value = &in_args[count_in_args];
- count_out_args++;
- count_in_args++;
- break;
- }
-
- if (arg_with_value != NULL)
- {
- add_out_arg (&builder,
- return_type,
- arg_with_value,
- dbus_method->out_args[dbus_arg_num++]);
- }
-
- g_base_info_unref ((GIBaseInfo *) arg);
+ ad = data->out_args->pdata[n];
+ gvariant_type = g_variant_type_new (ad->dbus_arg_info->signature);
+ value = convert_gi_to_gvariant ((GArgument *) out_args[n].v_pointer,
+ ad->type_info,
+ gvariant_type);
+ g_variant_builder_add_value (&builder, value);
+ g_variant_type_free (gvariant_type);
}
- g_assert_cmpint (num_args, ==, count_out_args);
-
- ret = g_variant_builder_end (&builder);
- return ret;
+ return g_variant_builder_end (&builder);
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -351,99 +931,88 @@ free_one_arg (GArgument *arg,
{
GITypeTag tag;
+ g_return_if_fail (arg != NULL);
+ g_return_if_fail (type != NULL);
+
tag = g_type_info_get_tag (type);
switch (tag)
{
+ case GI_TYPE_TAG_BOOLEAN:
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
+ case GI_TYPE_TAG_DOUBLE:
+ /* do nothing */
+ break;
+
case GI_TYPE_TAG_UTF8:
switch (transfer)
{
case GI_TRANSFER_NOTHING:
/* do nothing */
break;
+
case GI_TRANSFER_CONTAINER:
g_assert_not_reached ();
break;
+
case GI_TRANSFER_EVERYTHING:
g_free (arg->v_string);
break;
}
break;
+ case GI_TYPE_TAG_ARRAY:
+ /* TODO */
+ break;
+
default:
- /* Do nothing */
+ g_error ("Don't know how to free type tag `%s' with transfer `%s'",
+ g_type_tag_to_string (tag),
+ transfer == GI_TRANSFER_NOTHING ? "nothing" :
+ (transfer == GI_TRANSFER_CONTAINER ? "container" : "everything"));
break;
}
}
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
free_args (GArgument *return_value,
GArgument *in_args,
- guint num_in_args,
GArgument *out_args,
- GArgument *out_arg_values,
- guint num_out_args,
- GIFunctionInfo *method)
+ MethodData *data)
{
- GICallableInfo *callable;
- guint count_in_args;
- guint count_out_args;
guint n;
- GITypeInfo *return_type;
+ ArgData *ad;
- callable = (GICallableInfo *) method;
-
- return_type = g_callable_info_get_return_type (callable);
- if (g_type_info_get_tag (return_type) != GI_TYPE_TAG_VOID)
+ if (g_type_info_get_tag (data->return_value->type_info) != GI_TYPE_TAG_VOID)
{
- free_one_arg (return_value,
- return_type,
- g_callable_info_get_caller_owns (callable));
+ ad = data->return_value;
+ free_one_arg (return_value, ad->type_info, ad->transfer);
}
- //g_base_info_unref ((GIBaseInfo *) return_type);
- count_in_args = 0;
- count_out_args = 0;
- for (n = 0; n < (guint) g_callable_info_get_n_args (callable); n++)
+ /* want to skip this/self so start at 1 */
+ for (n = 1; n < data->in_args->len; n++)
{
- GIArgInfo *arg;
- GITypeInfo *type;
- GIDirection direction;
- GITransfer transfer;
- GArgument *arg_to_free;
-
- arg = g_callable_info_get_arg (callable, n);
- type = g_arg_info_get_type (arg);
- direction = g_arg_info_get_direction (arg);
- transfer = g_arg_info_get_ownership_transfer (arg);
-
- switch (direction)
- {
- case GI_DIRECTION_IN:
- /* do nothing */
- arg_to_free = &in_args[count_in_args++];
- break;
-
- case GI_DIRECTION_OUT:
- arg_to_free = &out_arg_values[count_out_args++];
- break;
-
- case GI_DIRECTION_INOUT:
- /* should be unused */
- g_assert (out_args[count_out_args].v_pointer == NULL);
- count_out_args++;
- arg_to_free = &in_args[count_in_args++];
- break;
- }
-
- free_one_arg (arg_to_free,
- type,
- transfer);
+ ad = data->in_args->pdata[n];
+ free_one_arg (&in_args[n], ad->type_info, ad->transfer);
+ }
- g_base_info_unref ((GIBaseInfo *) type);
- g_base_info_unref ((GIBaseInfo *) arg);
+ for (n = 0; n < data->out_args->len; n++)
+ {
+ ad = data->out_args->pdata[n];
+ /* if inout, it's already been freed in the loop */
+ if (ad->inout_in_arg_offset == -1)
+ free_one_arg (out_args[n].v_pointer, ad->type_info, ad->transfer);
}
- g_assert_cmpint (num_in_args, ==, count_in_args);
- g_assert_cmpint (num_out_args, ==, count_out_args);
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -465,13 +1034,12 @@ on_method_call (GDBusConnection *connection,
ExportData *data = user_data;
MethodData *method_data;
GError *error;
- GArgument return_value;
GArgument *in_args;
GArgument *out_args;
GArgument *out_arg_values;
- guint n;
gboolean deferred;
gboolean invocation_result;
+ GArgument return_value = {0};
in_args = NULL;
out_args = NULL;
@@ -482,23 +1050,18 @@ on_method_call (GDBusConnection *connection,
method_data = g_hash_table_lookup (data->dbus_method_name_to_method_data, method_name);
g_assert (method_data != NULL);
- /* First argument is the object (e.g. this/self) and not included in the arg count */
- in_args = g_new0 (GArgument, method_data->num_gi_in_args + 1);
- out_args = g_new0 (GArgument, method_data->num_gi_out_args);
- out_arg_values = g_new0 (GArgument, method_data->num_gi_out_args);
- n = 0;
- in_args[n++].v_pointer = data->object;
-
- prepare_in_args (parameters,
- in_args + 1,
- method_data->num_gi_in_args,
- method_data->method);
- prepare_out_args (&return_value,
- out_args,
- out_arg_values,
- method_data->num_gi_out_args,
- method_data->method,
- method_data->dbus_method);
+ in_args = g_new0 (GArgument, method_data->in_args->len);
+ out_args = g_new0 (GArgument, method_data->out_args->len);
+ out_arg_values = g_new0 (GArgument, method_data->out_args->len);
+
+ /* first is this/self */
+ in_args[0].v_pointer = data->object;
+
+ prepare_args (parameters,
+ in_args,
+ out_args,
+ out_arg_values,
+ method_data);
g_static_private_set (&gobject_invocation, invocation, NULL);
g_static_private_set (&gobject_invocation_object, g_object_ref (data->object), g_object_unref);
@@ -507,9 +1070,9 @@ on_method_call (GDBusConnection *connection,
error = NULL;
invocation_result = g_function_info_invoke (method_data->method,
in_args,
- method_data->num_gi_in_args + 1,
+ method_data->in_args->len,
out_args,
- method_data->num_gi_out_args,
+ method_data->out_args->len,
&return_value,
&error);
g_static_private_set (&gobject_invocation, NULL, NULL);
@@ -525,12 +1088,10 @@ on_method_call (GDBusConnection *connection,
if (!deferred)
{
GVariant *return_gvariant;
- return_gvariant = process_out_args (&return_value,
- in_args + 1, /* skip this/self */
- out_args,
- method_data->num_gi_out_args,
- method_data->method,
- method_data->dbus_method);
+ return_gvariant = process_args (&return_value,
+ in_args,
+ out_args,
+ method_data);
g_dbus_method_invocation_return_value (invocation, return_gvariant);
g_variant_unref (return_gvariant);
}
@@ -539,12 +1100,9 @@ on_method_call (GDBusConnection *connection,
if (in_args != NULL)
{
free_args (&return_value,
- in_args + 1, /* skip this/self */
- method_data->num_gi_in_args,
+ in_args,
out_args,
- out_arg_values,
- method_data->num_gi_out_args,
- method_data->method);
+ method_data);
g_free (in_args);
g_free (out_args);
g_free (out_arg_values);
@@ -668,14 +1226,17 @@ get_arg_info (GICallableInfo *callable,
GIArgInfo *arg,
GError **error)
{
- GITypeTag tag;
GITypeInfo *type;
GDBusArgInfo *ret;
- GVariantType *variant_type;
+ GVariantType *gvariant_type;
+ GVariantType *requested_gvariant_type;
const gchar *type_from_annotation;
const gchar *name;
ret = NULL;
+ type = NULL;
+ gvariant_type = NULL;
+ requested_gvariant_type = NULL;
type_from_annotation = NULL;
if (arg != NULL)
@@ -691,100 +1252,64 @@ get_arg_info (GICallableInfo *callable,
type_from_annotation = g_callable_info_get_return_attribute (callable, "gdbus.signature");
}
+ requested_gvariant_type = NULL;
if (type_from_annotation != NULL)
- {
- variant_type = g_variant_type_new (type_from_annotation);
- /* TODO: check that @type is actually compatible with @type_from_annotation */
- }
- else
- {
- tag = g_type_info_get_tag (type);
- switch (tag)
- {
- case GI_TYPE_TAG_BOOLEAN:
- variant_type = g_variant_type_new ("b");
- break;
- case GI_TYPE_TAG_INT8:
- variant_type = g_variant_type_new ("y");
- break;
- case GI_TYPE_TAG_UINT8:
- variant_type = g_variant_type_new ("y");
- break;
- case GI_TYPE_TAG_INT16:
- variant_type = g_variant_type_new ("n");
- break;
- case GI_TYPE_TAG_UINT16:
- variant_type = g_variant_type_new ("q");
- break;
- case GI_TYPE_TAG_INT:
- case GI_TYPE_TAG_INT32:
- variant_type = g_variant_type_new ("i");
- break;
- case GI_TYPE_TAG_UINT:
- case GI_TYPE_TAG_UINT32:
- variant_type = g_variant_type_new ("u");
- break;
- case GI_TYPE_TAG_INT64:
- variant_type = g_variant_type_new ("x");
- break;
- case GI_TYPE_TAG_UINT64:
- variant_type = g_variant_type_new ("t");
- break;
- case GI_TYPE_TAG_DOUBLE:
- variant_type = g_variant_type_new ("d");
- break;
- case GI_TYPE_TAG_UTF8:
- variant_type = g_variant_type_new ("s");
- break;
- case GI_TYPE_TAG_FILENAME:
- variant_type = g_variant_type_new ("ay");
- break;
- default:
- variant_type = NULL;
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- "Type tag `%s' not supported",
- g_type_tag_to_string (tag));
- goto out;
- }
- }
+ requested_gvariant_type = g_variant_type_new (type_from_annotation);
+ gvariant_type = get_gvariant_type_for_gi_type (type, requested_gvariant_type, error);
+ if (gvariant_type == NULL)
+ goto out;
ret = g_new0 (GDBusArgInfo, 1);
ret->ref_count = 1;
ret->name = g_strdup (name);
- ret->signature = g_variant_type_dup_string (variant_type);
+ ret->signature = g_variant_type_dup_string (gvariant_type);
+
+ g_print (" Using signature `%s' for param `%s'\n", ret->signature, ret->name);
out:
- g_base_info_unref ((GIBaseInfo *) type);
+ if (gvariant_type != NULL)
+ g_variant_type_free (gvariant_type);
+ if (requested_gvariant_type != NULL)
+ g_variant_type_free (requested_gvariant_type);
+ if (type != NULL)
+ g_base_info_unref ((GIBaseInfo *) type);
return ret;
}
-static GDBusMethodInfo *
-get_method_info (GIFunctionInfo *method,
+static MethodData *
+get_method_data (GIFunctionInfo *method,
const gchar *dbus_name,
- gint *num_gi_in_args,
- gint *num_gi_out_args,
GError **error)
{
- GDBusMethodInfo *ret;
+ MethodData *ret;
GICallableInfo *callable;
GITypeInfo *return_type;
- GPtrArray *in_args;
- GPtrArray *out_args;
+ GPtrArray *in_dbus_args;
+ GPtrArray *out_dbus_args;
+ ArgData *ad;
guint n;
- ret = NULL;
- in_args = g_ptr_array_new ();
- out_args = g_ptr_array_new ();
+ in_dbus_args = g_ptr_array_new ();
+ out_dbus_args = g_ptr_array_new ();
+
+ ret = g_new0 (MethodData, 1);
+ ret->method = g_base_info_ref ((GIBaseInfo *) method);
+ ret->in_args = g_ptr_array_new_with_free_func ((GDestroyNotify) arg_data_free);
+ ret->out_args = g_ptr_array_new_with_free_func ((GDestroyNotify) arg_data_free);
- *num_gi_in_args = 0;
- *num_gi_out_args = 0;
+ /* this/self */
+ ad = arg_data_new ();
+ g_ptr_array_add (ret->in_args, ad);
callable = (GICallableInfo *) method;
+ g_print ("Using dbus name `%s' for function `%s'\n", dbus_name, g_base_info_get_name ((GIBaseInfo *) method));
+
/* Handle return value, if any */
return_type = g_callable_info_get_return_type (callable);
+ ad = arg_data_new ();
+ ad->type_info = g_base_info_ref ((GIBaseInfo *) return_type);
+ ad->transfer = g_callable_info_get_caller_owns (callable);
if (g_type_info_get_tag (return_type) != GI_TYPE_TAG_VOID)
{
GDBusArgInfo *arg_info;
@@ -795,81 +1320,141 @@ get_method_info (GIFunctionInfo *method,
"Error processing return value of symbol `%s': ",
g_function_info_get_symbol (method));
g_base_info_unref ((GIBaseInfo *) return_type);
+ method_data_free (ret);
+ ret = NULL;
goto out;
}
- g_ptr_array_add (out_args, arg_info);
+ ad->dbus_arg_info = g_dbus_arg_info_ref (arg_info);
+ g_ptr_array_add (out_dbus_args, arg_info);
}
+ ret->return_value = ad;
//g_base_info_unref ((GIBaseInfo *) return_type);
/* Go through all parameters */
for (n = 0; n < (guint) g_callable_info_get_n_args (callable); n++)
{
GIArgInfo *arg;
+ GITypeInfo *type;
GIDirection direction;
GDBusArgInfo *arg_info;
+ gboolean not_on_dbus;
+ guint m;
+
+ /* Don't export arg on D-Bus if it's used for another arg (e.g. a length parameter for an array) */
+ not_on_dbus = FALSE;
arg = g_callable_info_get_arg (callable, n);
+ type = g_arg_info_get_type (arg);
- arg_info = get_arg_info (callable, arg, error);
- if (arg_info == NULL)
+ ad = arg_data_new ();
+ ad->arg_info = g_base_info_ref ((GIBaseInfo *) arg);
+ ad->type_info = g_arg_info_get_type (arg);
+ ad->transfer = g_arg_info_get_ownership_transfer (arg);
+
+ /* Now figure out if this arg is a length param for an array */
+ for (m = 0; m < (guint) g_callable_info_get_n_args (callable) && !not_on_dbus; m++)
{
- g_prefix_error (error,
- "Error processing argument `%s' of symbol `%s': ",
- g_base_info_get_name ((GIBaseInfo *) arg),
- g_function_info_get_symbol (method));
- g_base_info_unref ((GIBaseInfo *) arg);
- goto out;
+ GIArgInfo *other_arg;
+ GITypeInfo *other_type;
+ other_arg = g_callable_info_get_arg (callable, m);
+ other_type = g_arg_info_get_type (other_arg);
+ /* get_array_length() assumes first arg is this/self */
+ if (g_type_info_get_array_length (other_type) == (gint) n + 1)
+ {
+ not_on_dbus = TRUE;
+ ad->is_array_len_for_position = n;
+ }
+ g_base_info_unref ((GIBaseInfo *) other_type);
+ g_base_info_unref ((GIBaseInfo *) other_arg);
}
+ /* Set if this is an array using another arg as a length parameter */
+ ad->array_len_position = g_type_info_get_array_length (type);
+
+ arg_info = NULL;
+ if (!not_on_dbus)
+ {
+ arg_info = get_arg_info (callable, arg, error);
+ if (arg_info == NULL)
+ {
+ g_prefix_error (error,
+ "Error processing argument `%s' of symbol `%s': ",
+ g_base_info_get_name ((GIBaseInfo *) arg),
+ g_function_info_get_symbol (method));
+ g_base_info_unref ((GIBaseInfo *) arg);
+ g_base_info_unref ((GIBaseInfo *) type);
+ method_data_free (ret);
+ ret = NULL;
+ goto out;
+ }
+ }
+
+ ad->dbus_arg_info = arg_info != NULL ? g_dbus_arg_info_ref (arg_info) : NULL;
+
direction = g_arg_info_get_direction (arg);
switch (direction)
{
case GI_DIRECTION_IN:
- g_ptr_array_add (in_args, arg_info);
- *num_gi_in_args += 1;
+ if (arg_info != NULL)
+ g_ptr_array_add (in_dbus_args, arg_info);
+ g_ptr_array_add (ret->in_args, ad);
break;
case GI_DIRECTION_OUT:
- g_ptr_array_add (out_args, arg_info);
- *num_gi_out_args += 1;
+ if (arg_info != NULL)
+ g_ptr_array_add (out_dbus_args, arg_info);
+ g_ptr_array_add (ret->out_args, ad);
break;
case GI_DIRECTION_INOUT:
{
- gchar *s;
- s = g_strdup_printf ("in_%s", arg_info->name);
- g_free (arg_info->name);
- arg_info->name = s;
- g_ptr_array_add (in_args, arg_info);
- *num_gi_in_args += 1;
+ gchar *in_arg_name;
+ gchar *out_arg_name;
+
+ in_arg_name = g_strdup_printf ("in_%s", arg_info->name);
+ out_arg_name = g_strdup_printf ("out_%s", arg_info->name);
- arg_info = get_arg_info (callable, arg, NULL);
- g_assert (arg_info != NULL);
- s = g_strdup_printf ("out_%s", arg_info->name);
g_free (arg_info->name);
- arg_info->name = s;
- g_ptr_array_add (out_args, arg_info);
- *num_gi_out_args += 1;
- break;
+ arg_info->name = in_arg_name;
+ if (arg_info != NULL)
+ g_ptr_array_add (in_dbus_args, arg_info);
+ g_ptr_array_add (ret->in_args, ad);
+
+ ad = arg_data_dup_without_dbus_arg_info (ad);
+ ad->dbus_arg_info = get_arg_info (callable, arg, NULL);
+ g_assert (ad->dbus_arg_info != NULL);
+ g_free (ad->dbus_arg_info->name);
+ ad->dbus_arg_info->name = out_arg_name;
+ if (arg_info != NULL)
+ g_ptr_array_add (out_dbus_args, ad->dbus_arg_info);
+
+ ad->inout_in_arg_offset = ret->in_args->len - 1;
+
+ g_ptr_array_add (ret->out_args, ad);
}
+ break;
}
+
+ if (arg_info != NULL)
+ g_dbus_arg_info_unref (arg_info);
g_base_info_unref ((GIBaseInfo *) arg);
+ g_base_info_unref ((GIBaseInfo *) type);
}
- g_ptr_array_add (in_args, NULL);
- g_ptr_array_add (out_args, NULL);
+ g_ptr_array_add (in_dbus_args, NULL);
+ g_ptr_array_add (out_dbus_args, NULL);
- ret = g_new0 (GDBusMethodInfo, 1);
- ret->ref_count = 1;
- ret->name = g_strdup (dbus_name);
- g_ptr_array_ref (in_args);
- g_ptr_array_ref (out_args);
- ret->in_args = (GDBusArgInfo **) g_ptr_array_free (in_args, FALSE);
- ret->out_args = (GDBusArgInfo **) g_ptr_array_free (out_args, FALSE);
+ ret->dbus_method = g_new0 (GDBusMethodInfo, 1);
+ ret->dbus_method->ref_count = 1;
+ ret->dbus_method->name = g_strdup (dbus_name);
+ g_ptr_array_ref (in_dbus_args);
+ g_ptr_array_ref (out_dbus_args);
+ ret->dbus_method->in_args = (GDBusArgInfo **) g_ptr_array_free (in_dbus_args, FALSE);
+ ret->dbus_method->out_args = (GDBusArgInfo **) g_ptr_array_free (out_dbus_args, FALSE);
out:
- g_ptr_array_foreach (in_args, (GFunc) g_dbus_arg_info_unref, NULL);
- g_ptr_array_foreach (out_args, (GFunc) g_dbus_arg_info_unref, NULL);
- g_ptr_array_unref (in_args);
- g_ptr_array_unref (out_args);
+ g_ptr_array_foreach (in_dbus_args, (GFunc) g_dbus_arg_info_unref, NULL);
+ g_ptr_array_foreach (out_dbus_args, (GFunc) g_dbus_arg_info_unref, NULL);
+ g_ptr_array_unref (in_dbus_args);
+ g_ptr_array_unref (out_dbus_args);
return ret;
}
@@ -926,17 +1511,12 @@ compute_introspection_data (GObject *object,
dbus_name = g_base_info_get_attribute ((GIBaseInfo *) method, "gdbus.method");
if (dbus_name != NULL)
{
- GDBusMethodInfo *method_info;
MethodData *method_data;
- gint num_gi_in_args;
- gint num_gi_out_args;
- method_info = get_method_info (method,
+ method_data = get_method_data (method,
dbus_name,
- &num_gi_in_args,
- &num_gi_out_args,
error);
- if (method_info == NULL)
+ if (method_data == NULL)
{
g_ptr_array_foreach (method_infos, (GFunc) g_dbus_method_info_unref, NULL);
g_ptr_array_unref (method_infos);
@@ -944,13 +1524,9 @@ compute_introspection_data (GObject *object,
ret = NULL;
goto out;
}
- g_ptr_array_add (method_infos, method_info);
+ g_ptr_array_add (method_infos, method_data->dbus_method);
- method_data = g_new0 (MethodData, 1);
- method_data->method = g_base_info_ref ((GIBaseInfo *) method);
- method_data->dbus_method = g_dbus_method_info_ref (method_info);
- method_data->num_gi_in_args = num_gi_in_args;
- method_data->num_gi_out_args = num_gi_out_args;
+ method_data_dump (method_data, 0);
g_hash_table_insert (data->dbus_method_name_to_method_data,
g_strdup (dbus_name),
diff --git a/src/myfrobnicator.c b/src/myfrobnicator.c
index fc78fde..399ada5 100644
--- a/src/myfrobnicator.c
+++ b/src/myfrobnicator.c
@@ -21,6 +21,8 @@
#include "config.h"
+#include <stdlib.h>
+
#include "gdbusgi.h"
#include "myfrobnicator.h"
@@ -272,3 +274,55 @@ my_frobnicator_poke_path (MyFrobnicator *frobnicator,
return g_strdup_printf ("/another/object/path/here%s", object_path);
}
+
+/**
+ * my_frobnicator_test_arrays:
+ * @frobnicator:
+ * @carray_ai: (array length=carray_ai_len):
+ * @carray_ai_len:
+ * @carray_as:
+ * @gbytearray_ay: (element-type guint8):
+ * @garray_ai: (element-type gint):
+ * @garray_ad: (element-type gdouble):
+ * @gptrarray_as: (element-type utf8):
+ * @error:
+ *
+ * Returns: The sum of all elements.
+ *
+ * Attributes: (gdbus.method TestArrays)
+ */
+gdouble
+my_frobnicator_test_arrays (MyFrobnicator *frobnicator,
+ //gint *carray_ai,
+ //gint carray_ai_len,
+ const gchar *const *carray_as,
+ GByteArray *gbytearray_ay,
+ GArray *garray_ai,
+ GArray *garray_ad,
+ GPtrArray *gptrarray_as)
+{
+ gdouble ret;
+ guint n;
+
+ ret = 0.0;
+
+ //for (n = 0; n < carray_ai_len; n++)
+ // ret += carray_ai[n];
+
+ for (n = 0; carray_as[n] != NULL; n++)
+ ret += atof (carray_as[n]);
+
+ for (n = 0; n < gbytearray_ay->len; n++)
+ ret += gbytearray_ay->data[n];
+
+ for (n = 0; n < garray_ai->len; n++)
+ ret += g_array_index (garray_ai, gint, n);
+
+ for (n = 0; n < garray_ad->len; n++)
+ ret += g_array_index (garray_ad, gdouble, n);
+
+ for (n = 0; n < gptrarray_as->len; n++)
+ ret += atof (gptrarray_as->pdata[n]);
+
+ return ret;
+}
diff --git a/src/myfrobnicator.h b/src/myfrobnicator.h
index 92686b8..039f853 100644
--- a/src/myfrobnicator.h
+++ b/src/myfrobnicator.h
@@ -106,6 +106,14 @@ const gchar *my_frobnicator_return_const_str (MyFrobnicator *frobnicator,
gchar *my_frobnicator_poke_path (MyFrobnicator *frobnicator,
const gchar *object_path);
+gdouble my_frobnicator_test_arrays (MyFrobnicator *frobnicator,
+ //gint *carray_ai,
+ //gint carray_ai_len,
+ const gchar *const *carray_as,
+ GByteArray *gbytearray_ay,
+ GArray *garray_ai,
+ GArray *garray_ad,
+ GPtrArray *gptrarray_as);
G_END_DECLS
diff --git a/src/test.c b/src/test.c
index 1bdec4b..b17434c 100644
--- a/src/test.c
+++ b/src/test.c
@@ -21,7 +21,9 @@
#include "config.h"
+#include <math.h>
#include <gio/gio.h>
+
#include "gdbusgi.h"
#include <girepository.h>
@@ -51,6 +53,35 @@ on_bus_acquired (GDBusConnection *connection,
}
static void
+run_array_test (GDBusConnection *connection)
+{
+ GError *error;
+ GVariant *ret;
+ gdouble d;
+
+ error = NULL;
+ ret = g_dbus_connection_call_sync (connection,
+ "org.My.Service",
+ "/org/My/Frobnicator",
+ "org.MyProject.Frobnicator",
+ "TestArrays",
+ g_variant_new_parsed ("(['100', '200', '300'], "
+ " [@y 10, 20, 30], "
+ " [1, 2, 3], "
+ " [0.1, 0.2, 0.3], "
+ " ['0.01', '0.02', '0.03'])"),
+ G_VARIANT_TYPE ("(d)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL, /* GCancellable */
+ &error);
+ g_assert_no_error (error);
+ g_variant_get (ret, "(d)", &d);
+ g_assert_cmpfloat (fabs (d - 666.66), <, 1e-10);
+ g_variant_unref (ret);
+}
+
+static void
run_test (GDBusConnection *connection)
{
GError *error;
@@ -245,6 +276,8 @@ run_test (GDBusConnection *connection)
}
g_variant_unref (ret);
+ run_array_test (connection);
+
}
static gpointer