diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index 12eb83b..ffa0bd2 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -203,9 +203,12 @@ g_type_module_register_type g_type_module_add_interface g_type_module_register_enum g_type_module_register_flags +g_type_module_register_boxed G_DEFINE_DYNAMIC_TYPE G_DEFINE_DYNAMIC_TYPE_EXTENDED +G_DEFINE_DYNAMIC_BOXED_TYPE +G_DEFINE_DYNAMIC_BOXED_TYPE_WITH_CODE G_TYPE_MODULE diff --git a/docs/reference/gobject/tmpl/gtypemodule.sgml b/docs/reference/gobject/tmpl/gtypemodule.sgml index 8c46f67..abcfc07 100644 --- a/docs/reference/gobject/tmpl/gtypemodule.sgml +++ b/docs/reference/gobject/tmpl/gtypemodule.sgml @@ -192,6 +192,26 @@ not be unloaded. @Since: 2.6 + + +Looks up or registers a boxed type that is implemented with a particular +type plugin. If a type with name @type_name was previously registered, +the #GType identifier for the type is returned, otherwise the type +is newly registered, and the resulting #GType identifier returned. + + +As long as any instances of the type exist, the type plugin will +not be unloaded. + + +@module: a #GTypeModule +@name: name for the type +@boxed_copy: Boxed structure copy function. +@boxed_free: Boxed structure free function. +@Returns: the new or existing type ID +@Since: 2.18 + + A convenience macro for dynamic type implementations, which declares a @@ -284,3 +304,30 @@ gtk_gadget_register_type (GTypeModule *type_module) @Since: 2.14 + + +A convenience macro for dynamic boxed type implementations. +It defines a *_get_type() and a static +*_register_type() function for use in your +module_init(). + + +@name: Name of the new boxed type. +@boxed_copy: Boxed structure copy function. +@boxed_free: Boxed structure free function. +@Since: 2.18 + + + + +A more general version of G_DEFINE_DYNAMIC_BOXED_TYPE() which +allows to specify custom code in the *_register_type +function. + + +@name: Name of the new boxed type. +@boxed_copy: Boxed structure copy function. +@boxed_free: Boxed structure free function. +@Since: 2.18 + + diff --git a/gobject/gboxed.c b/gobject/gboxed.c index 7c9e6ad..c7bfb34 100644 --- a/gobject/gboxed.c +++ b/gobject/gboxed.c @@ -23,6 +23,7 @@ #include "gvaluearray.h" #include "gclosure.h" #include "gvaluecollector.h" +#include "gtypemodule.h" #include "gobjectalias.h" @@ -313,6 +314,56 @@ g_boxed_type_register_static (const gchar *name, return type; } +GType +g_type_module_register_boxed (GTypeModule *module, + const gchar *name, + GBoxedCopyFunc boxed_copy, + GBoxedFreeFunc boxed_free) +{ + const GTypeValueTable vtable = { + boxed_proxy_value_init, + boxed_proxy_value_free, + boxed_proxy_value_copy, + boxed_proxy_value_peek_pointer, + "p", + boxed_proxy_collect_value, + "p", + boxed_proxy_lcopy_value, + }; + const GTypeInfo type_info = { + 0, /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, /* instance_size */ + 0, /* n_preallocs */ + NULL, /* instance_init */ + &vtable, /* value_table */ + }; + GType type; + + g_return_val_if_fail (name != NULL, 0); + g_return_val_if_fail (boxed_copy != NULL, 0); + g_return_val_if_fail (boxed_free != NULL, 0); + + type = g_type_module_register_type (module, G_TYPE_BOXED, name, &type_info, 0); + + /* install proxy functions upon successfull registration */ + if (type) + { + BoxedNode key; + + key.type = type; + key.copy = boxed_copy; + key.free = boxed_free; + boxed_bsa = g_bsearch_array_replace (boxed_bsa, &boxed_bconfig, &key); + } + + return type; +} + gpointer g_boxed_copy (GType boxed_type, gconstpointer src_boxed) diff --git a/gobject/gobject.symbols b/gobject/gobject.symbols index 8597af3..e308ced 100644 --- a/gobject/gobject.symbols +++ b/gobject/gobject.symbols @@ -378,6 +378,7 @@ g_type_value_table_peek #if IN_FILE(__G_TYPE_MODULE_C__) g_type_module_add_interface g_type_module_get_type G_GNUC_CONST +g_type_module_register_boxed g_type_module_register_enum g_type_module_register_flags g_type_module_register_type diff --git a/gobject/gtypemodule.h b/gobject/gtypemodule.h index 46858f5..ad06379 100644 --- a/gobject/gtypemodule.h +++ b/gobject/gtypemodule.h @@ -25,6 +25,7 @@ #include #include +#include G_BEGIN_DECLS @@ -83,7 +84,7 @@ type_name##_get_type (void) \ { \ return type_name##_type_id; \ } \ -static void \ +static GType \ type_name##_register_type (GTypeModule *type_module) \ { \ GType g_define_type_id; \ @@ -106,6 +107,31 @@ type_name##_register_type (GTypeModule *type_module) \ (GTypeFlags) flags); \ g_define_type_id = type_name##_type_id; \ { CODE ; } \ + return g_define_type_id; \ +} + +#define G_DEFINE_DYNAMIC_BOXED_TYPE(TypeName, type_name, copy_func, free_func) G_DEFINE_DYNAMIC_BOXED_TYPE_EXTENDED (TypeName, type_name, copy_func, free_func, {}) +#define G_DEFINE_DYNAMIC_BOXED_TYPE_EXTENDED(TypeName, type_name, copy_func, free_func, CODE) \ +\ +static GType type_name##_type_id = 0; \ +\ +GType \ +type_name##_get_type (void) \ +{ \ + return type_name##_type_id; \ +} \ +static GType \ +type_name##_register_type (GTypeModule *type_module) \ +{ \ + GType g_define_type_id; \ + type_name##_type_id = \ + g_type_module_register_boxed (type_module, \ + #TypeName, \ + (GBoxedCopyFunc) copy_func, \ + (GBoxedFreeFunc) free_func); \ + g_define_type_id = type_name##_type_id; \ + { CODE ; } \ + return g_define_type_id; \ } @@ -129,6 +155,10 @@ GType g_type_module_register_enum (GTypeModule *module, GType g_type_module_register_flags (GTypeModule *module, const gchar *name, const GFlagsValue *const_static_values); +GType g_type_module_register_boxed (GTypeModule *module, + const gchar *name, + GBoxedCopyFunc boxed_copy, + GBoxedFreeFunc boxed_free); G_END_DECLS diff --git a/tests/gobject/dynamictype.c b/tests/gobject/dynamictype.c index 2a5415e..ed63b21 100644 --- a/tests/gobject/dynamictype.c +++ b/tests/gobject/dynamictype.c @@ -65,21 +65,51 @@ dynamic_object_init (DynamicObject *dynamic_object) { } +#define DYNAMIC_BOXED_TYPE (dynamic_boxed_get_type ()) +#define DYNAMIC_BOXED_MAGIC (42) + +typedef struct { + int value; +} DynamicBoxed; + +static DynamicBoxed * +dynamic_boxed_new (void) +{ + DynamicBoxed *boxed = g_new (DynamicBoxed, 1); + boxed->value = DYNAMIC_BOXED_MAGIC; + return boxed; +} + +static DynamicBoxed * +dynamic_boxed_copy (DynamicBoxed *boxed) +{ + DynamicBoxed *copy= g_new (DynamicBoxed, 1); + + copy->value = boxed->value; + return copy; +} + +static void +dynamic_boxed_free (DynamicBoxed *boxed) +{ + g_assert (boxed->value == DYNAMIC_BOXED_MAGIC); + g_free (boxed); +} + +G_DEFINE_DYNAMIC_BOXED_TYPE (DynamicBoxed, dynamic_boxed, dynamic_boxed_copy, dynamic_boxed_free); static void module_register (GTypeModule *module) { dynamic_object_register_type (module); + dynamic_boxed_register_type (module); } static void -test_dynamic_type (void) +test_dynamic_object (void) { - GTypeModule *module; DynamicObjectClass *class; - module = test_module_new (module_register); - /* Not loaded until we call ref for the first time */ class = g_type_class_peek (DYNAMIC_OBJECT_TYPE); g_assert (class == NULL); @@ -115,16 +145,57 @@ test_dynamic_type (void) g_assert (!loaded); } +static void +test_dynamic_boxed (gpointer data) +{ + GTypeValueTable *table; + GValue value = { 0, }; + DynamicBoxed *boxed, *copy; + + /* Not loaded until we call ref for the first time */ + g_assert (!loaded); + + /* Ref loads */ + g_value_init (&value, DYNAMIC_BOXED_TYPE); + g_value_take_boxed (&value, dynamic_boxed_new ()); + g_assert (loaded); + + /* Peek then works */ + table = g_type_value_table_peek (DYNAMIC_BOXED_TYPE); + g_assert (loaded); + + /* Unref causes finalize */ + g_value_unset (&value); + + /* Peek returns NULL */ + table = g_type_value_table_peek (DYNAMIC_BOXED_TYPE); + g_assert (!table); + g_assert (!loaded); + + /* Ref reloads */ + g_value_init (&value, DYNAMIC_BOXED_TYPE); + g_assert (loaded); + + /* And Unref causes finalize once more*/ + g_value_unset (&value); + table = g_type_value_table_peek (DYNAMIC_BOXED_TYPE); + g_assert (!table); + g_assert (!loaded); +} + int main (int argc, char *argv[]) { - g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) | - G_LOG_LEVEL_WARNING | - G_LOG_LEVEL_CRITICAL); + GTypeModule *module; + + g_test_init (&argc, &argv, NULL); g_type_init (); - test_dynamic_type (); + module = test_module_new (module_register); + + g_test_add_func ("/DynamicObject", test_dynamic_object); + g_test_add_func ("/DynamicBoxed", test_dynamic_boxed); - return 0; + return g_test_run (); }