mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-06 17:36:14 +01:00
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()`.
|