mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
7b2ac3c82e
Signed-off-by: Philip Withnall <pwithnall@gnome.org> Helps: #3037
114 lines
3.4 KiB
Markdown
114 lines
3.4 KiB
Markdown
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 type’s ‘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()`.
|