| 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()`. |