docs: Move boxed type documentation to Markdown

And add some additional new content and examples.

Helps: #3037
This commit is contained in:
Matthias Clasen 2023-10-09 23:16:13 +01:00 committed by Philip Withnall
parent 1a090564d2
commit 24e93078d3
4 changed files with 115 additions and 29 deletions

View File

@ -0,0 +1,113 @@
Title: Boxed types
# Boxed types
A "boxed type" is a generic wrapper mechanism for arbitrary C structures.
The only thing the type system needs to know about the structures is how to
copy them (a [`callback@GObject.BoxedCopyFunc`]) and how to free them (a
[`callback@GObject.BoxedFreeFunc`])—beyond that they are treated as opaque
chunks of memory.
Boxed types are useful for simple value-holder structures like rectangles or
points. They can also be used for wrapping structures defined in non-GObject
based libraries. They allow arbitrary structures to be handled in a uniform
way, allowing uniform copying (or referencing) and freeing (or
unreferencing) of them, and uniform representation of the type of the
contained structure. In turn, this allows any type which can be boxed to be
set as the data in a `GValue`, which allows for polymorphic handling of a much
wider range of data types, and hence usage of such types as `GObject` property
values.
All boxed types inherit from the `G_TYPE_BOXED` fundamental type.
It is very important to note that boxed types are **not** deeply
inheritable: you cannot register a boxed type that inherits from another
boxed type. This means you cannot create your own custom, parallel type
hierarchy and map it to GType using boxed types. If you want to have deeply
inheritable types without using GObject, you will need to use
`GTypeInstance`.
## Registering a new boxed type
The recommended way to register a new boxed type is to use the
[`func@GObject.DEFINE_BOXED_TYPE`] macro:
```c
// In the header
#define EXAMPLE_TYPE_RECTANGLE (example_rectangle_get_type())
typedef struct {
double x, y;
double width, height;
} ExampleRectangle;
GType
example_rectangle_get_type (void);
ExampleRectangle *
example_rectangle_copy (ExampleRectangle *r);
void
example_rectangle_free (ExampleRectangle *r);
// In the source
G_DEFINE_BOXED_TYPE (ExampleRectangle, example_rectangle,
example_rectangle_copy,
example_rectangle_free)
```
Just like `G_DEFINE_TYPE` and `G_DEFINE_INTERFACE_TYPE`, the
`G_DEFINE_BOXED_TYPE` macro will provide the definition of the `get_type()`
function, which will call [`func@GObject.boxed_type_register_static`] with
the given type name as well as the `GBoxedCopyFunc` and `GBoxedFreeFunc`
functions.
## Using boxed types
### Object properties
In order to use a boxed type with GObject properties you will need to
register the property using [`func@GObject.param_spec_boxed`], e.g.
```c
obj_props[PROP_BOUNDS] =
g_param_spec_boxed ("bounds", NULL, NULL,
EXAMPLE_TYPE_RECTANGLE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
```
In the `set_property` implementation you can use `g_value_get_boxed()` to
retrieve a pointer to the boxed type:
```c
switch (prop_id)
{
// ...
case PROP_BOUNDS:
example_object_set_bounds (self, g_value_get_boxed (value));
break;
// ...
}
```
Similarly, you can use `g_value_set_boxed()` in the implementation of the
`get_property` virtual function:
```c
switch (prop_id)
{
// ...
case PROP_BOUNDS:
g_value_set_boxed (self, &self->bounds);
break;
// ...
}
```
## Reference counting
Boxed types are designed so that reference counted types can be boxed. Use
the types ref function as the `GBoxedCopyFunc`, and its unref function as
the `GBoxedFreeFunc`. For example, for `GBytes`, the `GBoxedCopyFunc` is
`g_bytes_ref()`, and the GBoxedFreeFunc is `g_bytes_unref()`.

View File

@ -42,6 +42,7 @@ show_class_hierarchy = true
urlmap_file = "urlmap.js" urlmap_file = "urlmap.js"
# The same order will be used when generating the index # The same order will be used when generating the index
content_files = [ content_files = [
"boxed.md",
] ]
content_images = [ content_images = [
] ]

View File

@ -71,6 +71,7 @@ endif
# gi-docgen version # gi-docgen version
expand_content_files = [ expand_content_files = [
'boxed.md',
] ]
gobject_gir = meson.current_source_dir() / 'GObject-2.0.gir' gobject_gir = meson.current_source_dir() / 'GObject-2.0.gir'

View File

@ -33,35 +33,6 @@
#include "gvaluearray.h" #include "gvaluearray.h"
#include "gvaluecollector.h" #include "gvaluecollector.h"
/**
* SECTION:gboxed
* @short_description: A mechanism to wrap opaque C structures registered
* by the type system
* @see_also: #GParamSpecBoxed, g_param_spec_boxed()
* @title: Boxed Types
*
* #GBoxed is a generic wrapper mechanism for arbitrary C structures.
*
* The only thing the type system needs to know about the structures is how to
* copy them (a #GBoxedCopyFunc) and how to free them (a #GBoxedFreeFunc);
* beyond that, they are treated as opaque chunks of memory.
*
* Boxed types are useful for simple value-holder structures like rectangles or
* points. They can also be used for wrapping structures defined in non-#GObject
* based libraries. They allow arbitrary structures to be handled in a uniform
* way, allowing uniform copying (or referencing) and freeing (or unreferencing)
* of them, and uniform representation of the type of the contained structure.
* In turn, this allows any type which can be boxed to be set as the data in a
* #GValue, which allows for polymorphic handling of a much wider range of data
* types, and hence usage of such types as #GObject property values.
*
* #GBoxed is designed so that reference counted types can be boxed. Use the
* types ref function as the #GBoxedCopyFunc, and its unref function as the
* #GBoxedFreeFunc. For example, for #GBytes, the #GBoxedCopyFunc is
* g_bytes_ref(), and the #GBoxedFreeFunc is g_bytes_unref().
*/
static inline void /* keep this function in sync with gvalue.c */ static inline void /* keep this function in sync with gvalue.c */
value_meminit (GValue *value, value_meminit (GValue *value,
GType value_type) GType value_type)