2023-11-29 13:13:13 +01:00
|
|
|
|
Title: Boxed Types
|
2023-10-10 00:16:13 +02:00
|
|
|
|
|
2023-11-29 13:13:13 +01:00
|
|
|
|
# Boxed Types
|
2023-10-10 00:16:13 +02:00
|
|
|
|
|
|
|
|
|
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()`.
|