mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-09 04:15:49 +01:00
Allow proper introspection of GTypeValueTable
The introspection scanner cannot deal very well with function pointers into a plain structure. In order to document the various function pointers in GTypeValueTable we need to create typed callbacks, and use them to replace the anonymous function pointers inside the structure. This not only allows us to properly document the function pointers, but it also allows us to annotate the arguments and return value of those function pointers. See also: https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/400#note_1721707
This commit is contained in:
parent
32ec11e51d
commit
23a9dbdaf6
@ -25,6 +25,12 @@ GTypeClass
|
|||||||
GTypeInfo
|
GTypeInfo
|
||||||
GTypeFundamentalInfo
|
GTypeFundamentalInfo
|
||||||
GInterfaceInfo
|
GInterfaceInfo
|
||||||
|
GTypeValueInitFunc
|
||||||
|
GTypeValueFreeFunc
|
||||||
|
GTypeValueCopyFunc
|
||||||
|
GTypeValuePeekPointerFunc
|
||||||
|
GTypeValueCollectFunc
|
||||||
|
GTypeValueLCopyFunc
|
||||||
GTypeValueTable
|
GTypeValueTable
|
||||||
G_TYPE_FROM_INSTANCE
|
G_TYPE_FROM_INSTANCE
|
||||||
G_TYPE_FROM_CLASS
|
G_TYPE_FROM_CLASS
|
||||||
|
312
gobject/gtype.h
312
gobject/gtype.h
@ -1164,75 +1164,120 @@ struct _GInterfaceInfo
|
|||||||
GInterfaceFinalizeFunc interface_finalize;
|
GInterfaceFinalizeFunc interface_finalize;
|
||||||
gpointer interface_data;
|
gpointer interface_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GTypeValueTable:
|
* GTypeValueInitFunc:
|
||||||
* @value_init: Default initialize @values contents by poking values
|
* @value: the value to initialize
|
||||||
* directly into the value->data array. The data array of
|
*
|
||||||
* the #GValue passed into this function was zero-filled
|
* Initializes the value contents by setting the fields of the `value->data`
|
||||||
* with `memset()`, so no care has to be taken to free any
|
* array.
|
||||||
* old contents. E.g. for the implementation of a string
|
*
|
||||||
* value that may never be %NULL, the implementation might
|
* The data array of the #GValue passed into this function was zero-filled
|
||||||
* look like:
|
* with `memset()`, so no care has to be taken to free any old contents.
|
||||||
|
* For example, in the case of a string value that may never be %NULL, the
|
||||||
|
* implementation might look like:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* value->data[0].v_pointer = g_strdup ("");
|
* value->data[0].v_pointer = g_strdup ("");
|
||||||
* ]|
|
* ]|
|
||||||
* @value_free: Free any old contents that might be left in the
|
*
|
||||||
* data array of the passed in @value. No resources may
|
* Since: 2.78
|
||||||
* remain allocated through the #GValue contents after
|
*/
|
||||||
* this function returns. E.g. for our above string type:
|
typedef void (* GTypeValueInitFunc) (GValue *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GTypeValueFreeFunc:
|
||||||
|
* @value: the value to free
|
||||||
|
*
|
||||||
|
* Frees any old contents that might be left in the `value->data` array of
|
||||||
|
* the given value.
|
||||||
|
*
|
||||||
|
* No resources may remain allocated through the #GValue contents after this
|
||||||
|
* function returns. E.g. for our above string type:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* // only free strings without a specific flag for static storage
|
* // only free strings without a specific flag for static storage
|
||||||
* if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
|
* if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
|
||||||
* g_free (value->data[0].v_pointer);
|
* g_free (value->data[0].v_pointer);
|
||||||
* ]|
|
* ]|
|
||||||
* @value_copy: @dest_value is a #GValue with zero-filled data section
|
*
|
||||||
* and @src_value is a properly setup #GValue of same or
|
* Since: 2.78
|
||||||
* derived type.
|
*/
|
||||||
* The purpose of this function is to copy the contents of
|
typedef void (* GTypeValueFreeFunc) (GValue *value);
|
||||||
* @src_value into @dest_value in a way, that even after
|
|
||||||
* @src_value has been freed, the contents of @dest_value
|
/**
|
||||||
* remain valid. String type example:
|
* GTypeValueCopyFunc:
|
||||||
|
* @src_value: the value to copy
|
||||||
|
* @dest_value: (out): the location of the copy
|
||||||
|
*
|
||||||
|
* Copies the content of a #GValue into another.
|
||||||
|
*
|
||||||
|
* The @dest_value is a #GValue with zero-filled data section and @src_value
|
||||||
|
* is a properly initialized #GValue of same type, or derived type.
|
||||||
|
*
|
||||||
|
* The purpose of this function is to copy the contents of @src_value
|
||||||
|
* into @dest_value in a way, that even after @src_value has been freed, the
|
||||||
|
* contents of @dest_value remain valid. String type example:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* dest_value->data[0].v_pointer = g_strdup (src_value->data[0].v_pointer);
|
* dest_value->data[0].v_pointer = g_strdup (src_value->data[0].v_pointer);
|
||||||
* ]|
|
* ]|
|
||||||
* @value_peek_pointer: If the value contents fit into a pointer, such as objects
|
*
|
||||||
* or strings, return this pointer, so the caller can peek at
|
* Since: 2.78
|
||||||
* the current contents. To extend on our above string example:
|
*/
|
||||||
|
typedef void (* GTypeValueCopyFunc) (const GValue *src_value,
|
||||||
|
GValue *dest_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GTypeValuePeekPointerFunc:
|
||||||
|
* @value: the value to peek
|
||||||
|
*
|
||||||
|
* If the value contents fit into a pointer, such as objects or strings,
|
||||||
|
* return this pointer, so the caller can peek at the current contents.
|
||||||
|
*
|
||||||
|
* To extend on our above string example:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* return value->data[0].v_pointer;
|
* return value->data[0].v_pointer;
|
||||||
* ]|
|
* ]|
|
||||||
* @collect_format: A string format describing how to collect the contents of
|
*
|
||||||
* this value bit-by-bit. Each character in the format represents
|
* Returns: (transfer none): a pointer to the value contents
|
||||||
* an argument to be collected, and the characters themselves indicate
|
*
|
||||||
* the type of the argument. Currently supported arguments are:
|
* Since: 2.78
|
||||||
* - 'i' - Integers. passed as collect_values[].v_int.
|
*/
|
||||||
* - 'l' - Longs. passed as collect_values[].v_long.
|
typedef gpointer (* GTypeValuePeekPointerFunc) (const GValue *value);
|
||||||
* - 'd' - Doubles. passed as collect_values[].v_double.
|
|
||||||
* - 'p' - Pointers. passed as collect_values[].v_pointer.
|
/**
|
||||||
* It should be noted that for variable argument list construction,
|
* GTypeValueCollectFunc:
|
||||||
* ANSI C promotes every type smaller than an integer to an int, and
|
* @value: the value to initialize
|
||||||
* floats to doubles. So for collection of short int or char, 'i'
|
* @n_collect_values: the number of collected values
|
||||||
* needs to be used, and for collection of floats 'd'.
|
* @collect_values: (array length=n_collect_values): the collected values
|
||||||
* @collect_value: The collect_value() function is responsible for converting the
|
* @collect_flags: optional flags
|
||||||
* values collected from a variable argument list into contents
|
*
|
||||||
* suitable for storage in a GValue. This function should setup
|
* This function is responsible for converting the values collected from
|
||||||
* @value similar to value_init(); e.g. for a string value that
|
* a variadic argument list into contents suitable for storage in a #GValue.
|
||||||
* does not allow %NULL pointers, it needs to either spew an error,
|
*
|
||||||
* or do an implicit conversion by storing an empty string.
|
* This function should setup @value similar to #GTypeValueInitFunc; e.g.
|
||||||
* The @value passed in to this function has a zero-filled data
|
* for a string value that does not allow `NULL` pointers, it needs to either
|
||||||
* array, so just like for value_init() it is guaranteed to not
|
* emit an error, or do an implicit conversion by storing an empty string.
|
||||||
* contain any old contents that might need freeing.
|
*
|
||||||
* @n_collect_values is exactly the string length of @collect_format,
|
* The @value passed in to this function has a zero-filled data array, so
|
||||||
* and @collect_values is an array of unions #GTypeCValue with
|
* just like for #GTypeValueInitFunc it is guaranteed to not contain any old
|
||||||
* length @n_collect_values, containing the collected values
|
* contents that might need freeing.
|
||||||
* according to @collect_format.
|
*
|
||||||
* @collect_flags is an argument provided as a hint by the caller.
|
* The @n_collect_values argument is the string length of the `collect_format`
|
||||||
* It may contain the flag %G_VALUE_NOCOPY_CONTENTS indicating,
|
* field of #GTypeValueTable, and `collect_values` is an array of #GTypeCValue
|
||||||
* that the collected value contents may be considered "static"
|
* with length of @n_collect_values, containing the collected values according
|
||||||
* for the duration of the @value lifetime.
|
* to `collect_format`.
|
||||||
* Thus an extra copy of the contents stored in @collect_values is
|
*
|
||||||
|
* The @collect_flags argument provided as a hint by the caller. It may
|
||||||
|
* contain the flag %G_VALUE_NOCOPY_CONTENTS indicating that the collected
|
||||||
|
* value contents may be considered ‘static’ for the duration of the @value
|
||||||
|
* lifetime. Thus an extra copy of the contents stored in @collect_values is
|
||||||
* not required for assignment to @value.
|
* not required for assignment to @value.
|
||||||
|
*
|
||||||
* For our above string example, we continue with:
|
* For our above string example, we continue with:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* if (!collect_values[0].v_pointer)
|
* if (!collect_values[0].v_pointer)
|
||||||
* value->data[0].v_pointer = g_strdup ("");
|
* value->data[0].v_pointer = g_strdup ("");
|
||||||
@ -1246,97 +1291,156 @@ struct _GInterfaceInfo
|
|||||||
* value->data[0].v_pointer = g_strdup (collect_values[0].v_pointer);
|
* value->data[0].v_pointer = g_strdup (collect_values[0].v_pointer);
|
||||||
* return NULL;
|
* return NULL;
|
||||||
* ]|
|
* ]|
|
||||||
|
*
|
||||||
* It should be noted, that it is generally a bad idea to follow the
|
* It should be noted, that it is generally a bad idea to follow the
|
||||||
* %G_VALUE_NOCOPY_CONTENTS hint for reference counted types. Due to
|
* %G_VALUE_NOCOPY_CONTENTS hint for reference counted types. Due to
|
||||||
* reentrancy requirements and reference count assertions performed
|
* reentrancy requirements and reference count assertions performed
|
||||||
* by the signal emission code, reference counts should always be
|
* by the signal emission code, reference counts should always be
|
||||||
* incremented for reference counted contents stored in the value->data
|
* incremented for reference counted contents stored in the `value->data`
|
||||||
* array. To deviate from our string example for a moment, and taking
|
* array. To deviate from our string example for a moment, and taking
|
||||||
* a look at an exemplary implementation for collect_value() of
|
* a look at an exemplary implementation for `GTypeValueTable.collect_value()`
|
||||||
* #GObject:
|
* of `GObject`:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* GObject *object = G_OBJECT (collect_values[0].v_pointer);
|
* GObject *object = G_OBJECT (collect_values[0].v_pointer);
|
||||||
* g_return_val_if_fail (object != NULL,
|
* g_return_val_if_fail (object != NULL,
|
||||||
* g_strdup_printf ("Object passed as invalid NULL pointer"));
|
* g_strdup_printf ("Object %p passed as invalid NULL pointer", object));
|
||||||
* // never honour G_VALUE_NOCOPY_CONTENTS for ref-counted types
|
* // never honour G_VALUE_NOCOPY_CONTENTS for ref-counted types
|
||||||
* value->data[0].v_pointer = g_object_ref (object);
|
* value->data[0].v_pointer = g_object_ref (object);
|
||||||
* return NULL;
|
* return NULL;
|
||||||
* ]|
|
* ]|
|
||||||
* The reference count for valid objects is always incremented,
|
*
|
||||||
* regardless of @collect_flags. For invalid objects, the example
|
* The reference count for valid objects is always incremented, regardless
|
||||||
* returns a newly allocated string without altering @value.
|
* of `collect_flags`. For invalid objects, the example returns a newly
|
||||||
* Upon success, collect_value() needs to return %NULL. If, however,
|
* allocated string without altering `value`.
|
||||||
* an error condition occurred, collect_value() may spew an
|
*
|
||||||
* error by returning a newly allocated non-%NULL string, giving
|
* Upon success, `collect_value()` needs to return `NULL`. If, however,
|
||||||
* a suitable description of the error condition.
|
* an error condition occurred, `collect_value()` should return a newly
|
||||||
* The calling code makes no assumptions about the @value
|
* allocated string containing an error diagnostic.
|
||||||
* contents being valid upon error returns, @value
|
*
|
||||||
* is simply thrown away without further freeing. As such, it is
|
* The calling code makes no assumptions about the `value` contents being
|
||||||
* a good idea to not allocate #GValue contents, prior to returning
|
* valid upon error returns, `value` is simply thrown away without further
|
||||||
* an error, however, collect_values() is not obliged to return
|
* freeing. As such, it is a good idea to not allocate `GValue` contents
|
||||||
* a correctly setup @value for error returns, simply because
|
* prior to returning an error; however, `collect_values()` is not obliged
|
||||||
* any non-%NULL return is considered a fatal condition so further
|
* to return a correctly setup @value for error returns, simply because
|
||||||
* program behaviour is undefined.
|
* any non-`NULL` return is considered a fatal programming error, and
|
||||||
* @lcopy_format: Format description of the arguments to collect for @lcopy_value,
|
* further program behaviour is undefined.
|
||||||
* analogous to @collect_format. Usually, @lcopy_format string consists
|
*
|
||||||
* only of 'p's to provide lcopy_value() with pointers to storage locations.
|
* Returns: (transfer full) (nullable): `NULL` on success, otherwise a
|
||||||
* @lcopy_value: This function is responsible for storing the @value contents into
|
* newly allocated error string on failure
|
||||||
* arguments passed through a variable argument list which got
|
*
|
||||||
* collected into @collect_values according to @lcopy_format.
|
* Since: 2.78
|
||||||
* @n_collect_values equals the string length of @lcopy_format,
|
*/
|
||||||
* and @collect_flags may contain %G_VALUE_NOCOPY_CONTENTS.
|
typedef gchar * (* GTypeValueCollectFunc) (GValue *value,
|
||||||
* In contrast to collect_value(), lcopy_value() is obliged to
|
guint n_collect_values,
|
||||||
* always properly support %G_VALUE_NOCOPY_CONTENTS.
|
GTypeCValue *collect_values,
|
||||||
* Similar to collect_value() the function may prematurely abort
|
guint collect_flags);
|
||||||
* by returning a newly allocated string describing an error condition.
|
|
||||||
* To complete the string example:
|
/**
|
||||||
|
* GTypeValueLCopyFunc:
|
||||||
|
* @value: the value to lcopy
|
||||||
|
* @n_collect_values: the number of collected values
|
||||||
|
* @collect_values: (array length=n_collect_values): the collected
|
||||||
|
* locations for storage
|
||||||
|
* @collect_flags: optional flags
|
||||||
|
*
|
||||||
|
* This function is responsible for storing the `value`
|
||||||
|
* contents into arguments passed through a variadic argument list which
|
||||||
|
* got collected into `collect_values` according to `lcopy_format`.
|
||||||
|
*
|
||||||
|
* The `n_collect_values` argument equals the string length of
|
||||||
|
* `lcopy_format`, and `collect_flags` may contain %G_VALUE_NOCOPY_CONTENTS.
|
||||||
|
*
|
||||||
|
* In contrast to #GTypeValueCollectFunc, this function is obliged to always
|
||||||
|
* properly support %G_VALUE_NOCOPY_CONTENTS.
|
||||||
|
*
|
||||||
|
* Similar to #GTypeValueCollectFunc the function may prematurely abort by
|
||||||
|
* returning a newly allocated string describing an error condition. To
|
||||||
|
* complete the string example:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* gchar **string_p = collect_values[0].v_pointer;
|
* gchar **string_p = collect_values[0].v_pointer;
|
||||||
* g_return_val_if_fail (string_p != NULL,
|
* g_return_val_if_fail (string_p != NULL,
|
||||||
* g_strdup_printf ("string location passed as NULL"));
|
* g_strdup ("string location passed as NULL"));
|
||||||
|
*
|
||||||
* if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
|
* if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
|
||||||
* *string_p = value->data[0].v_pointer;
|
* *string_p = value->data[0].v_pointer;
|
||||||
* else
|
* else
|
||||||
* *string_p = g_strdup (value->data[0].v_pointer);
|
* *string_p = g_strdup (value->data[0].v_pointer);
|
||||||
* ]|
|
* ]|
|
||||||
* And an illustrative version of lcopy_value() for
|
*
|
||||||
* reference-counted types:
|
* And an illustrative version of this function for reference-counted
|
||||||
|
* types:
|
||||||
|
*
|
||||||
* |[<!-- language="C" -->
|
* |[<!-- language="C" -->
|
||||||
* GObject **object_p = collect_values[0].v_pointer;
|
* GObject **object_p = collect_values[0].v_pointer;
|
||||||
* g_return_val_if_fail (object_p != NULL,
|
* g_return_val_if_fail (object_p != NULL,
|
||||||
* g_strdup_printf ("object location passed as NULL"));
|
* g_strdup ("object location passed as NULL"));
|
||||||
* if (!value->data[0].v_pointer)
|
*
|
||||||
|
* if (value->data[0].v_pointer == NULL)
|
||||||
* *object_p = NULL;
|
* *object_p = NULL;
|
||||||
* else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) // always honour
|
* else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) // always honour
|
||||||
* *object_p = value->data[0].v_pointer;
|
* *object_p = value->data[0].v_pointer;
|
||||||
* else
|
* else
|
||||||
* *object_p = g_object_ref (value->data[0].v_pointer);
|
* *object_p = g_object_ref (value->data[0].v_pointer);
|
||||||
|
*
|
||||||
* return NULL;
|
* return NULL;
|
||||||
* ]|
|
* ]|
|
||||||
*
|
*
|
||||||
|
* Returns: (transfer full) (nullable): `NULL` on success, otherwise
|
||||||
|
* a newly allocated error string on failure
|
||||||
|
*
|
||||||
|
* Since: 2.78
|
||||||
|
*/
|
||||||
|
typedef gchar * (* GTypeValueLCopyFunc) (const GValue *value,
|
||||||
|
guint n_collect_values,
|
||||||
|
GTypeCValue *collect_values,
|
||||||
|
guint collect_flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GTypeValueTable:
|
||||||
|
* @value_init: Function to initialize a GValue
|
||||||
|
* @value_free: Function to free a GValue
|
||||||
|
* @value_copy: Function to copy a GValue
|
||||||
|
* @value_peek_pointer: Function to peek the contents of a GValue if they fit
|
||||||
|
* into a pointer
|
||||||
|
* @collect_format: A string format describing how to collect the contents of
|
||||||
|
* this value bit-by-bit. Each character in the format represents
|
||||||
|
* an argument to be collected, and the characters themselves indicate
|
||||||
|
* the type of the argument. Currently supported arguments are:
|
||||||
|
* - `'i'`: Integers, passed as `collect_values[].v_int`
|
||||||
|
* - `'l'`: Longs, passed as `collect_values[].v_long`
|
||||||
|
* - `'d'`: Doubles, passed as `collect_values[].v_double`
|
||||||
|
* - `'p'`: Pointers, passed as `collect_values[].v_pointer`
|
||||||
|
* It should be noted that for variable argument list construction,
|
||||||
|
* ANSI C promotes every type smaller than an integer to an int, and
|
||||||
|
* floats to doubles. So for collection of short int or char, `'i'`
|
||||||
|
* needs to be used, and for collection of floats `'d'`.
|
||||||
|
* @collect_value: Function to initialize a GValue from the values
|
||||||
|
* collected from variadic arguments
|
||||||
|
* @lcopy_format: Format description of the arguments to collect for @lcopy_value,
|
||||||
|
* analogous to @collect_format. Usually, @lcopy_format string consists
|
||||||
|
* only of `'p'`s to provide lcopy_value() with pointers to storage locations.
|
||||||
|
* @lcopy_value: Function to store the contents of a value into the
|
||||||
|
* locations collected from variadic arguments
|
||||||
|
*
|
||||||
* The #GTypeValueTable provides the functions required by the #GValue
|
* The #GTypeValueTable provides the functions required by the #GValue
|
||||||
* implementation, to serve as a container for values of a type.
|
* implementation, to serve as a container for values of a type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct _GTypeValueTable
|
struct _GTypeValueTable
|
||||||
{
|
{
|
||||||
void (*value_init) (GValue *value);
|
GTypeValueInitFunc value_init;
|
||||||
void (*value_free) (GValue *value);
|
GTypeValueFreeFunc value_free;
|
||||||
void (*value_copy) (const GValue *src_value,
|
GTypeValueCopyFunc value_copy;
|
||||||
GValue *dest_value);
|
GTypeValuePeekPointerFunc value_peek_pointer;
|
||||||
/* varargs functionality (optional) */
|
|
||||||
gpointer (*value_peek_pointer) (const GValue *value);
|
|
||||||
const gchar *collect_format;
|
const gchar *collect_format;
|
||||||
gchar* (*collect_value) (GValue *value,
|
GTypeValueCollectFunc collect_value;
|
||||||
guint n_collect_values,
|
|
||||||
GTypeCValue *collect_values,
|
|
||||||
guint collect_flags);
|
|
||||||
const gchar *lcopy_format;
|
const gchar *lcopy_format;
|
||||||
gchar* (*lcopy_value) (const GValue *value,
|
GTypeValueLCopyFunc lcopy_value;
|
||||||
guint n_collect_values,
|
|
||||||
GTypeCValue *collect_values,
|
|
||||||
guint collect_flags);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GOBJECT_AVAILABLE_IN_ALL
|
GOBJECT_AVAILABLE_IN_ALL
|
||||||
GType g_type_register_static (GType parent_type,
|
GType g_type_register_static (GType parent_type,
|
||||||
const gchar *type_name,
|
const gchar *type_name,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user