diff --git a/docs/reference/gobject/boxed.md b/docs/reference/gobject/boxed.md new file mode 100644 index 000000000..f4d79e2a8 --- /dev/null +++ b/docs/reference/gobject/boxed.md @@ -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 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()`. diff --git a/docs/reference/gobject/gobject.toml.in b/docs/reference/gobject/gobject.toml.in index 8f14ff542..c963b2fb1 100644 --- a/docs/reference/gobject/gobject.toml.in +++ b/docs/reference/gobject/gobject.toml.in @@ -42,6 +42,7 @@ show_class_hierarchy = true urlmap_file = "urlmap.js" # The same order will be used when generating the index content_files = [ + "boxed.md", ] content_images = [ ] diff --git a/docs/reference/gobject/meson.build b/docs/reference/gobject/meson.build index a88e4b0d8..0eba6d1a7 100644 --- a/docs/reference/gobject/meson.build +++ b/docs/reference/gobject/meson.build @@ -71,6 +71,7 @@ endif # gi-docgen version expand_content_files = [ + 'boxed.md', ] gobject_gir = meson.current_source_dir() / 'GObject-2.0.gir' diff --git a/gobject/gboxed.c b/gobject/gboxed.c index 819e95229..2deaff401 100644 --- a/gobject/gboxed.c +++ b/gobject/gboxed.c @@ -33,35 +33,6 @@ #include "gvaluearray.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 - * 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(). - */ - static inline void /* keep this function in sync with gvalue.c */ value_meminit (GValue *value, GType value_type)