mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 15:06:14 +01:00
Add g_value_take_variant
Turns out we do need g_value_take_variant(), so we can correctly implement VARIANT:* marshalers. Bug #621947.
This commit is contained in:
parent
052ef2614a
commit
db68f8203a
@ -708,6 +708,7 @@ g_param_spec_variant
|
|||||||
g_value_get_variant
|
g_value_get_variant
|
||||||
g_value_dup_variant
|
g_value_dup_variant
|
||||||
g_value_set_variant
|
g_value_set_variant
|
||||||
|
g_value_take_variant
|
||||||
|
|
||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
g_value_set_instance
|
g_value_set_instance
|
||||||
|
@ -249,7 +249,7 @@ complete_out_arg (OutArgument *oarg)
|
|||||||
{ "BOXED", "BOXED", "gpointer", "g_value_take_boxed", },
|
{ "BOXED", "BOXED", "gpointer", "g_value_take_boxed", },
|
||||||
{ "POINTER", "POINTER", "gpointer", "g_value_set_pointer", },
|
{ "POINTER", "POINTER", "gpointer", "g_value_set_pointer", },
|
||||||
{ "OBJECT", "OBJECT", "GObject*", "g_value_take_object", },
|
{ "OBJECT", "OBJECT", "GObject*", "g_value_take_object", },
|
||||||
{ "VARIANT", "VARIANT", "GVariant*", "g_value_set_variant", },
|
{ "VARIANT", "VARIANT", "GVariant*", "g_value_take_variant", },
|
||||||
/* deprecated: */
|
/* deprecated: */
|
||||||
{ "NONE", "VOID", "void", NULL, },
|
{ "NONE", "VOID", "void", NULL, },
|
||||||
{ "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", },
|
{ "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", },
|
||||||
|
@ -299,6 +299,7 @@ g_value_get_gtype
|
|||||||
g_value_get_variant
|
g_value_get_variant
|
||||||
g_value_dup_variant
|
g_value_dup_variant
|
||||||
g_value_set_variant
|
g_value_set_variant
|
||||||
|
g_value_take_variant
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -184,6 +184,13 @@ G_BEGIN_DECLS
|
|||||||
*
|
*
|
||||||
* The fundamental type corresponding to #GVariant.
|
* The fundamental type corresponding to #GVariant.
|
||||||
*
|
*
|
||||||
|
* All floating #GVariant instances passed through the #GType system are
|
||||||
|
* consumed.
|
||||||
|
*
|
||||||
|
* Note that callbacks in closures, and signal handlers
|
||||||
|
* for signals of return type %G_TYPE_VARIANT, must never return floating
|
||||||
|
* variants.
|
||||||
|
*
|
||||||
* Note: GLib 2.24 did include a boxed type with this name. It was replaced
|
* Note: GLib 2.24 did include a boxed type with this name. It was replaced
|
||||||
* with this fundamental type in 2.26.
|
* with this fundamental type in 2.26.
|
||||||
*
|
*
|
||||||
|
@ -1206,6 +1206,45 @@ g_value_set_variant (GValue *value,
|
|||||||
g_variant_unref (old_variant);
|
g_variant_unref (old_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_value_take_variant:
|
||||||
|
* @value: a valid #GValue of %G_TYPE_VARIANT
|
||||||
|
* @variant: a #GVariant, or %NULL
|
||||||
|
*
|
||||||
|
* Set the contents of a variant #GValue to @variant, and takes over
|
||||||
|
* the ownership of the caller's reference to @variant;
|
||||||
|
* the caller doesn't have to unref it any more (i.e. the reference
|
||||||
|
* count of the variant is not increased).
|
||||||
|
*
|
||||||
|
* It is a programmer error to pass a floating variant to this function.
|
||||||
|
* In particular this means that callbacks in closures, and signal handlers
|
||||||
|
* for signals of return type %G_TYPE_VARIANT, must never return floating
|
||||||
|
* variants.
|
||||||
|
*
|
||||||
|
* If you want the #GValue to hold its own reference to @variant, use
|
||||||
|
* g_value_set_variant() instead.
|
||||||
|
*
|
||||||
|
* This is an internal function introduced mainly for C marshallers.
|
||||||
|
*
|
||||||
|
* Since: 2.26
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_value_take_variant (GValue *value,
|
||||||
|
GVariant *variant)
|
||||||
|
{
|
||||||
|
GVariant *old_variant;
|
||||||
|
|
||||||
|
g_return_if_fail (G_VALUE_HOLDS_VARIANT (value));
|
||||||
|
g_return_if_fail (variant == NULL || !g_variant_is_floating (variant));
|
||||||
|
|
||||||
|
old_variant = value->data[0].v_pointer;
|
||||||
|
|
||||||
|
value->data[0].v_pointer = variant;
|
||||||
|
|
||||||
|
if (old_variant)
|
||||||
|
g_variant_unref (old_variant);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_value_get_variant:
|
* g_value_get_variant:
|
||||||
* @value: a valid #GValue of %G_TYPE_VARIANT
|
* @value: a valid #GValue of %G_TYPE_VARIANT
|
||||||
|
@ -225,6 +225,8 @@ void g_value_set_gtype (GValue *value,
|
|||||||
GType g_value_get_gtype (const GValue *value);
|
GType g_value_get_gtype (const GValue *value);
|
||||||
void g_value_set_variant (GValue *value,
|
void g_value_set_variant (GValue *value,
|
||||||
GVariant *variant);
|
GVariant *variant);
|
||||||
|
void g_value_take_variant (GValue *value,
|
||||||
|
GVariant *variant);
|
||||||
GVariant* g_value_get_variant (const GValue *value);
|
GVariant* g_value_get_variant (const GValue *value);
|
||||||
GVariant* g_value_dup_variant (const GValue *value);
|
GVariant* g_value_dup_variant (const GValue *value);
|
||||||
|
|
||||||
|
@ -58,6 +58,8 @@ struct _TestObjectClass
|
|||||||
gint param);
|
gint param);
|
||||||
gboolean (*test_signal2) (TestObject *tobject,
|
gboolean (*test_signal2) (TestObject *tobject,
|
||||||
gint param);
|
gint param);
|
||||||
|
GVariant* (*test_signal3) (TestObject *tobject,
|
||||||
|
gboolean *weak_ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
static GType test_object_get_type (void);
|
static GType test_object_get_type (void);
|
||||||
@ -155,11 +157,70 @@ test_object_signal2_callback_after (TestObject *tobject,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
test_signal3_accumulator (GSignalInvocationHint *ihint,
|
||||||
|
GValue *return_accu,
|
||||||
|
const GValue *handler_return,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GVariant *variant;
|
||||||
|
|
||||||
|
variant = g_value_get_variant (handler_return);
|
||||||
|
g_assert (!g_variant_is_floating (variant));
|
||||||
|
|
||||||
|
g_value_set_variant (return_accu, variant);
|
||||||
|
|
||||||
|
return variant == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To be notified when the variant is finalised, we construct
|
||||||
|
* it from data with a custom GDestroyNotify.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *mem;
|
||||||
|
gsize n;
|
||||||
|
gboolean *weak_ptr;
|
||||||
|
} VariantData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_data (VariantData *data)
|
||||||
|
{
|
||||||
|
*(data->weak_ptr) = TRUE;
|
||||||
|
g_free (data->mem);
|
||||||
|
g_slice_free (VariantData, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
test_object_real_signal3 (TestObject *tobject,
|
||||||
|
gboolean *weak_ptr)
|
||||||
|
{
|
||||||
|
GVariant *variant;
|
||||||
|
VariantData *data;
|
||||||
|
|
||||||
|
variant = g_variant_ref_sink (g_variant_new_uint32 (42));
|
||||||
|
data = g_slice_new (VariantData);
|
||||||
|
data->weak_ptr = weak_ptr;
|
||||||
|
data->n = g_variant_get_size (variant);
|
||||||
|
data->mem = g_malloc (data->n);
|
||||||
|
g_variant_store (variant, data->mem);
|
||||||
|
g_variant_unref (variant);
|
||||||
|
|
||||||
|
variant = g_variant_new_from_data (G_VARIANT_TYPE ("u"),
|
||||||
|
data->mem,
|
||||||
|
data->n,
|
||||||
|
TRUE,
|
||||||
|
(GDestroyNotify) free_data,
|
||||||
|
data);
|
||||||
|
return g_variant_ref_sink (variant);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_object_class_init (TestObjectClass *class)
|
test_object_class_init (TestObjectClass *class)
|
||||||
{
|
{
|
||||||
class->test_signal1 = test_object_real_signal1;
|
class->test_signal1 = test_object_real_signal1;
|
||||||
class->test_signal2 = test_object_real_signal2;
|
class->test_signal2 = test_object_real_signal2;
|
||||||
|
class->test_signal3 = test_object_real_signal3;
|
||||||
|
|
||||||
g_signal_new ("test-signal1",
|
g_signal_new ("test-signal1",
|
||||||
G_OBJECT_CLASS_TYPE (class),
|
G_OBJECT_CLASS_TYPE (class),
|
||||||
@ -175,6 +236,13 @@ test_object_class_init (TestObjectClass *class)
|
|||||||
g_signal_accumulator_true_handled, NULL,
|
g_signal_accumulator_true_handled, NULL,
|
||||||
test_marshal_BOOLEAN__INT,
|
test_marshal_BOOLEAN__INT,
|
||||||
G_TYPE_BOOLEAN, 1, G_TYPE_INT);
|
G_TYPE_BOOLEAN, 1, G_TYPE_INT);
|
||||||
|
g_signal_new ("test-signal3",
|
||||||
|
G_OBJECT_CLASS_TYPE (class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (TestObjectClass, test_signal3),
|
||||||
|
test_signal3_accumulator, NULL,
|
||||||
|
test_marshal_VARIANT__POINTER,
|
||||||
|
G_TYPE_VARIANT, 1, G_TYPE_POINTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_TYPE(TestObject, test_object,
|
static DEFINE_TYPE(TestObject, test_object,
|
||||||
@ -188,6 +256,8 @@ main (int argc,
|
|||||||
TestObject *object;
|
TestObject *object;
|
||||||
gchar *string_result;
|
gchar *string_result;
|
||||||
gboolean bool_result;
|
gboolean bool_result;
|
||||||
|
gboolean variant_finalised;
|
||||||
|
GVariant *variant_result;
|
||||||
|
|
||||||
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
|
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
|
||||||
G_LOG_LEVEL_WARNING |
|
G_LOG_LEVEL_WARNING |
|
||||||
@ -223,5 +293,16 @@ main (int argc,
|
|||||||
g_signal_emit_by_name (object, "test-signal2", 4, &bool_result);
|
g_signal_emit_by_name (object, "test-signal2", 4, &bool_result);
|
||||||
g_assert (bool_result == FALSE);
|
g_assert (bool_result == FALSE);
|
||||||
|
|
||||||
|
variant_finalised = FALSE;
|
||||||
|
variant_result = NULL;
|
||||||
|
g_signal_emit_by_name (object, "test-signal3", &variant_finalised, &variant_result);
|
||||||
|
g_assert (variant_result != NULL);
|
||||||
|
g_assert (!g_variant_is_floating (variant_result));
|
||||||
|
|
||||||
|
/* Test that variant_result had refcount 1 */
|
||||||
|
g_assert (!variant_finalised);
|
||||||
|
g_variant_unref (variant_result);
|
||||||
|
g_assert (variant_finalised);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Marshallers used in tests
|
# Marshallers used in tests
|
||||||
BOOLEAN:INT
|
BOOLEAN:INT
|
||||||
STRING:INT
|
STRING:INT
|
||||||
|
VARIANT:POINTER
|
||||||
|
Loading…
Reference in New Issue
Block a user