+/**
+ * g_dbus_gvariant_to_gvalue:
+ * @value: A #GVariant.
+ * @out_gvalue: (out): Return location pointing to a zero-filled (uninitialized) #GValue.
+ *
+ * Converts a #GVariant to a #GValue. If @value is floating, it is consumed.
+ *
+ * The rules specified in the g_dbus_gvalue_to_gvariant() function are
+ * used - this function is essentially its reverse form.
+ *
+ * The conversion never fails - a valid #GValue is always returned in
+ * @out_gvalue.
+ *
+ * Since: 2.30
+ */
+void
+g_dbus_gvariant_to_gvalue (GVariant *value,
+ GValue *out_gvalue)
+{
+ const GVariantType *type;
+ gchar **array;
+
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (out_gvalue != NULL);
+
+ memset (out_gvalue, '\0', sizeof (GValue));
+
+ switch (g_variant_classify (value))
+ {
+ case G_VARIANT_CLASS_BOOLEAN:
+ g_value_init (out_gvalue, G_TYPE_BOOLEAN);
+ g_value_set_boolean (out_gvalue, g_variant_get_boolean (value));
+ break;
+
+ case G_VARIANT_CLASS_BYTE:
+ g_value_init (out_gvalue, G_TYPE_UCHAR);
+ g_value_set_uchar (out_gvalue, g_variant_get_byte (value));
+ break;
+
+ case G_VARIANT_CLASS_INT16:
+ g_value_init (out_gvalue, G_TYPE_INT);
+ g_value_set_int (out_gvalue, g_variant_get_int16 (value));
+ break;
+
+ case G_VARIANT_CLASS_UINT16:
+ g_value_init (out_gvalue, G_TYPE_UINT);
+ g_value_set_uint (out_gvalue, g_variant_get_uint16 (value));
+ break;
+
+ case G_VARIANT_CLASS_INT32:
+ g_value_init (out_gvalue, G_TYPE_INT);
+ g_value_set_int (out_gvalue, g_variant_get_int32 (value));
+ break;
+
+ case G_VARIANT_CLASS_UINT32:
+ g_value_init (out_gvalue, G_TYPE_UINT);
+ g_value_set_uint (out_gvalue, g_variant_get_uint32 (value));
+ break;
+
+ case G_VARIANT_CLASS_INT64:
+ g_value_init (out_gvalue, G_TYPE_INT64);
+ g_value_set_int64 (out_gvalue, g_variant_get_int64 (value));
+ break;
+
+ case G_VARIANT_CLASS_UINT64:
+ g_value_init (out_gvalue, G_TYPE_UINT64);
+ g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
+ break;
+
+ case G_VARIANT_CLASS_DOUBLE:
+ g_value_init (out_gvalue, G_TYPE_DOUBLE);
+ g_value_set_double (out_gvalue, g_variant_get_double (value));
+ break;
+
+ case G_VARIANT_CLASS_STRING:
+ g_value_init (out_gvalue, G_TYPE_STRING);
+ g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
+ break;
+
+ case G_VARIANT_CLASS_OBJECT_PATH:
+ g_value_init (out_gvalue, G_TYPE_STRING);
+ g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
+ break;
+
+ case G_VARIANT_CLASS_SIGNATURE:
+ g_value_init (out_gvalue, G_TYPE_STRING);
+ g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
+ break;
+
+ case G_VARIANT_CLASS_ARRAY:
+ type = g_variant_get_type (value);
+ switch (g_variant_type_peek_string (type)[1])
+ {
+ case G_VARIANT_CLASS_BYTE:
+ g_value_init (out_gvalue, G_TYPE_STRING);
+ g_value_set_string (out_gvalue, g_variant_get_bytestring (value));
+ break;
+
+ case G_VARIANT_CLASS_STRING:
+ g_value_init (out_gvalue, G_TYPE_STRV);
+ array = g_variant_dup_strv (value, NULL);
+ g_value_take_boxed (out_gvalue, array);
+ break;
+
+ case G_VARIANT_CLASS_OBJECT_PATH:
+ g_value_init (out_gvalue, G_TYPE_STRV);
+ array = g_variant_dup_objv (value, NULL);
+ g_value_take_boxed (out_gvalue, array);
+ break;
+
+ case G_VARIANT_CLASS_ARRAY:
+ switch (g_variant_type_peek_string (type)[2])
+ {
+ case G_VARIANT_CLASS_BYTE:
+ g_value_init (out_gvalue, G_TYPE_STRV);
+ array = g_variant_dup_bytestring_array (value, NULL);
+ g_value_take_boxed (out_gvalue, array);
+ break;
+
+ default:
+ g_value_init (out_gvalue, G_TYPE_VARIANT);
+ g_value_set_variant (out_gvalue, value);
+ break;
+ }
+ break;
+
+ default:
+ g_value_init (out_gvalue, G_TYPE_VARIANT);
+ g_value_set_variant (out_gvalue, value);
+ break;
+ }
+ break;
+
+ case G_VARIANT_CLASS_HANDLE:
+ case G_VARIANT_CLASS_VARIANT:
+ case G_VARIANT_CLASS_MAYBE:
+ case G_VARIANT_CLASS_TUPLE:
+ case G_VARIANT_CLASS_DICT_ENTRY:
+ g_value_init (out_gvalue, G_TYPE_VARIANT);
+ g_value_set_variant (out_gvalue, value);
+ break;
+ }
+}
+