From 9a4a10fbc8b3cdee2f6d82ab7e1d92945ed6566e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 29 Jun 2022 14:02:51 +0100 Subject: [PATCH 1/7] Add G_DEFINE macros for enum and flags types While you might want to use automated tools like glib-mkenums to generate enumeration types for your library, it's often not entirely necessary to complicate your build system in order to handle a couple of enumerations with few values. Just like we have G_DEFINE macros for object, interface, pointer, and boxed types, we should provide macros for defining enum and flags types. --- gobject/genums.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/gobject/genums.h b/gobject/genums.h index c66ce45c0..dfa4e6fb2 100644 --- a/gobject/genums.h +++ b/gobject/genums.h @@ -274,6 +274,94 @@ void g_flags_complete_type_info (GType g_flags_type, GTypeInfo *info, const GFlagsValue *const_values); +/* {{{ Macros */ + +/** + * G_DEFINE_ENUM_VALUE: + * @EnumValue: an enumeration value + * @EnumNick: a short string representing the enumeration value + * + * Defines an enumeration value, and maps it to a "nickname". + * + * This macro can only be used with G_DEFINE_ENUM_TYPE() and + * G_DEFINE_FLAGS_TYPE(). + * + * Since: 2.74 + */ +#define G_DEFINE_ENUM_VALUE(EnumValue, EnumNick) { EnumValue, #EnumValue, EnumNick }, + +/** + * G_DEFINE_ENUM_TYPE: + * @TypeName: the enumeration type, in `CamelCase` + * @type_name: the enumeration type prefixed, in `snake_case` + * @values: a list of enumeration values, defined using G_DEFINE_ENUM_VALUE() + * + * A convenience macro for defining enumeration types. + * + * This macro will generate a `*_get_type()` function for the + * given @TypeName, using @type_name as the function prefix. + * + * |[ + * G_DEFINE_ENUM_TYPE (GtkOrientation, gtk_orientation, + * G_DEFINE_ENUM_VALUE (GTK_ORIENTATION_HORIZONTAL, "horizontal") + * G_DEFINE_ENUM_VALUE (GTK_ORIENTATION_VERTICAL, "vertical")) + * ]| + * + * Since: 2.74 + */ +#define G_DEFINE_ENUM_TYPE(TypeName, type_name, values) \ +GType \ +type_name ## _get_type (void) { \ + static gsize g_define_type__static = 0; \ + if (g_once_init_enter (&g_define_type__static)) { \ + static const GEnumValue enum_values[] = { \ + values \ + { 0, NULL, NULL }, \ + }; \ + GType g_define_type = g_enum_register_static (g_intern_static_string (#TypeName), enum_values); \ + g_once_init_leave (&g_define_type__static, g_define_type); \ + } \ + return g_define_type__static; \ +} + +/** + * G_DEFINE_FLAGS_TYPE: + * @TypeName: the enumeration type, in `CamelCase` + * @type_name: the enumeration type prefixed, in `snake_case` + * @values: a list of enumeration values, defined using G_DEFINE_ENUM_VALUE() + * + * A convenience macro for defining flag types. + * + * This macro will generate a `*_get_type()` function for the + * given @TypeName, using @type_name as the function prefix. + * + * |[ + * G_DEFINE_FLAGS_TYPE (GSettingsBindFlags, g_settings_bind_flags, + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_DEFAULT, "default") + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_GET, "get") + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_SET, "set") + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_NO_SENSITIVITY, "no-sensitivity") + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_GET_NO_CHANGES, "get-no-changes") + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_INVERT_BOOLEAN, "invert-boolean")) + * ]| + * + * Since: 2.74 + */ +#define G_DEFINE_FLAGS_TYPE(TypeName, type_name, values) \ +GType \ +type_name ## _get_type (void) { \ + static gsize g_define_type__static = 0; \ + if (g_once_init_enter (&g_define_type__static)) { \ + static const GFlagsValue flags_values[] = { \ + values \ + { 0, NULL, NULL }, \ + }; \ + GType g_define_type = g_flags_register_static (g_intern_static_string (#TypeName), flags_values); \ + g_once_init_leave (&g_define_type__static, g_define_type); \ + } \ + return g_define_type__static; \ +} + G_END_DECLS #endif /* __G_ENUMS_H__ */ From 2a9ef1e0b4b73161598921f2dba6085e2cc5b8ed Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 29 Jun 2022 14:05:22 +0100 Subject: [PATCH 2/7] Test the newly added G_DEFINE macros for enumeration types --- gobject/tests/enums.c | 73 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/gobject/tests/enums.c b/gobject/tests/enums.c index 3b9641790..447d76c0f 100644 --- a/gobject/tests/enums.c +++ b/gobject/tests/enums.c @@ -158,13 +158,86 @@ test_flags_basic (void) g_type_class_unref (class); } +typedef enum { + TEST_ENUM_FIRST_VALUE, + TEST_ENUM_SECOND_VALUE, + TEST_ENUM_THIRD_VALUE +} TestEnum; + +GType test_enum_get_type (void); + +G_DEFINE_ENUM_TYPE (TestEnum, test_enum, + G_DEFINE_ENUM_VALUE (TEST_ENUM_FIRST_VALUE, "first-value") + G_DEFINE_ENUM_VALUE (TEST_ENUM_SECOND_VALUE, "second-value") + G_DEFINE_ENUM_VALUE (TEST_ENUM_THIRD_VALUE, "third-value")) + +static void +test_enum_define_type (void) +{ + GEnumClass *class = g_type_class_ref (test_enum_get_type ()); + GEnumValue *val; + + g_assert_cmpint (class->minimum, ==, 0); + g_assert_cmpint (class->maximum, ==, 2); + g_assert_cmpint (class->n_values, ==, 3); + + val = g_enum_get_value (class, 2); + g_assert (val != NULL); + g_assert_cmpstr (val->value_nick, ==, "third-value"); + val = g_enum_get_value (class, 15); + g_assert (val == NULL); + + g_type_class_unref (class); +} + +typedef enum { + TEST_FLAGS_DEFAULT = 0, + TEST_FLAGS_FIRST = 1 << 0, + TEST_FLAGS_SECOND = 1 << 1, + TEST_FLAGS_THIRD = 1 << 2 +} TestFlags; + +GType test_flags_get_type (void); + +G_DEFINE_FLAGS_TYPE (TestFlags, test_flags, + G_DEFINE_ENUM_VALUE (TEST_FLAGS_DEFAULT, "default") + G_DEFINE_ENUM_VALUE (TEST_FLAGS_FIRST, "first") + G_DEFINE_ENUM_VALUE (TEST_FLAGS_SECOND, "second") + G_DEFINE_ENUM_VALUE (TEST_FLAGS_THIRD, "third")) + +static void +test_flags_define_type (void) +{ + GFlagsClass *class = g_type_class_ref (test_flags_get_type ()); + GFlagsValue *val; + char *to_string; + + g_assert_cmpint (class->mask, ==, 1 | 2 | 4); + g_assert_cmpint (class->n_values, ==, 4); + + val = g_flags_get_first_value (class, 2|4); + g_assert (val != NULL); + g_assert_cmpstr (val->value_nick, ==, "second"); + + val = g_flags_get_first_value (class, 8); + g_assert (val == NULL); + + to_string = g_flags_to_string (test_flags_get_type (), 0); + g_assert_cmpstr (to_string, ==, "TEST_FLAGS_DEFAULT"); + g_free (to_string); + + g_type_class_unref (class); +} + int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/enum/basic", test_enum_basic); + g_test_add_func ("/enum/define-type", test_enum_define_type); g_test_add_func ("/flags/basic", test_flags_basic); + g_test_add_func ("/flags/define-type", test_flags_define_type); return g_test_run (); } From 28edd84e77250582ac8bc409c23ebcd31916c511 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 29 Jun 2022 14:06:36 +0100 Subject: [PATCH 3/7] docs: Add the new G_DEFINE macros for enumeration types --- docs/reference/gobject/gobject-sections.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index dc1c89e3e..4107f8356 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -129,6 +129,9 @@ G_DEFINE_BOXED_TYPE G_DEFINE_BOXED_TYPE_WITH_CODE G_DEFINE_POINTER_TYPE G_DEFINE_POINTER_TYPE_WITH_CODE +G_DEFINE_ENUM_VALUE +G_DEFINE_ENUM_TYPE +G_DEFINE_FLAGS_TYPE G_TYPE_FUNDAMENTAL_SHIFT From 6cbf7a7461695866df10d0c559f0898c9b3cdb0c Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 29 Jun 2022 15:37:13 +0100 Subject: [PATCH 4/7] Port enums tests to the appropriate assert functions Do not use `g_assert()` inside tests, as the symbol can be disabled. Instead, use `g_assert_null()` and `g_assert_nonnull()`. --- gobject/tests/enums.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/gobject/tests/enums.c b/gobject/tests/enums.c index 447d76c0f..0c465172d 100644 --- a/gobject/tests/enums.c +++ b/gobject/tests/enums.c @@ -20,7 +20,7 @@ test_enum_basic (void) type = g_enum_register_static ("MyEnum", my_enum_values); g_value_init (&value, type); - g_assert (G_VALUE_HOLDS_ENUM (&value)); + g_assert_true (G_VALUE_HOLDS_ENUM (&value)); g_value_set_enum (&value, 2); g_assert_cmpint (g_value_get_enum (&value), ==, 2); @@ -33,22 +33,22 @@ test_enum_basic (void) g_assert_cmpint (class->n_values, ==, 3); val = g_enum_get_value (class, 2); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpstr (val->value_name, ==, "the second value"); val = g_enum_get_value (class, 15); - g_assert (val == NULL); + g_assert_null (val); val = g_enum_get_value_by_name (class, "the third value"); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpint (val->value, ==, 3); val = g_enum_get_value_by_name (class, "the color purple"); - g_assert (val == NULL); + g_assert_null (val); val = g_enum_get_value_by_nick (class, "one"); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpint (val->value, ==, 1); val = g_enum_get_value_by_nick (class, "purple"); - g_assert (val == NULL); + g_assert_null (val); to_string = g_enum_to_string (type, 2); g_assert_cmpstr (to_string, ==, "the second value"); @@ -100,7 +100,7 @@ test_flags_basic (void) no_default_flag_values); g_value_init (&value, type); - g_assert (G_VALUE_HOLDS_FLAGS (&value)); + g_assert_true (G_VALUE_HOLDS_FLAGS (&value)); g_value_set_flags (&value, 2|8); g_assert_cmpint (g_value_get_flags (&value), ==, 2|8); @@ -111,22 +111,22 @@ test_flags_basic (void) g_assert_cmpint (class->n_values, ==, 4); val = g_flags_get_first_value (class, 2|8); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpstr (val->value_name, ==, "the second flag"); val = g_flags_get_first_value (class, 16); - g_assert (val == NULL); + g_assert_null (val); val = g_flags_get_value_by_name (class, "the third flag"); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpint (val->value, ==, 8); val = g_flags_get_value_by_name (class, "the color purple"); - g_assert (val == NULL); + g_assert_null (val); val = g_flags_get_value_by_nick (class, "one"); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpint (val->value, ==, 1); val = g_flags_get_value_by_nick (class, "purple"); - g_assert (val == NULL); + g_assert_null (val); test_flags_transform_to_string (&value); g_value_unset (&value); @@ -182,10 +182,10 @@ test_enum_define_type (void) g_assert_cmpint (class->n_values, ==, 3); val = g_enum_get_value (class, 2); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpstr (val->value_nick, ==, "third-value"); val = g_enum_get_value (class, 15); - g_assert (val == NULL); + g_assert_null (val); g_type_class_unref (class); } @@ -216,11 +216,11 @@ test_flags_define_type (void) g_assert_cmpint (class->n_values, ==, 4); val = g_flags_get_first_value (class, 2|4); - g_assert (val != NULL); + g_assert_nonnull (val); g_assert_cmpstr (val->value_nick, ==, "second"); val = g_flags_get_first_value (class, 8); - g_assert (val == NULL); + g_assert_null (val); to_string = g_flags_to_string (test_flags_get_type (), 0); g_assert_cmpstr (to_string, ==, "TEST_FLAGS_DEFAULT"); From fa05ebe27c4209336a56bcd9ed27572bd7f21b43 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 29 Jun 2022 15:44:36 +0100 Subject: [PATCH 5/7] docs: Mention alternatives for defining enumeration types We should mention glib-mkenums in the documentation for G_DEFINE_ENUM_TYPE and G_DEFINE_FLAGS_TYPE. We should also mention the macros in the documentation for glib-mkenums. This way, developers can choose the most appropriate tool for their use case. --- docs/reference/gobject/glib-mkenums.xml | 6 ++++++ gobject/genums.h | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/docs/reference/gobject/glib-mkenums.xml b/docs/reference/gobject/glib-mkenums.xml index ce250a3ff..29709853c 100644 --- a/docs/reference/gobject/glib-mkenums.xml +++ b/docs/reference/gobject/glib-mkenums.xml @@ -44,6 +44,12 @@ input. The options specified control the text that generated, substituting vario keywords enclosed in @ characters in the templates. +Since version 2.74, GLib provides the G_DEFINE_ENUM_TYPE +and G_DEFINE_FLAGS_TYPE C pre-processor macros. These macros +can be used to define a GType for projects that have few, small enumeration +types without going through the complexities of generating code at build +time. + Production text substitutions Certain keywords enclosed in @ characters will be substituted in the diff --git a/gobject/genums.h b/gobject/genums.h index dfa4e6fb2..2cd5000f9 100644 --- a/gobject/genums.h +++ b/gobject/genums.h @@ -307,6 +307,10 @@ void g_flags_complete_type_info (GType g_flags_type, * G_DEFINE_ENUM_VALUE (GTK_ORIENTATION_VERTICAL, "vertical")) * ]| * + * For projects that have multiple enumeration types, or enumeration + * types with many values, you should consider using glib-mkenums to + * generate the type function. + * * Since: 2.74 */ #define G_DEFINE_ENUM_TYPE(TypeName, type_name, values) \ @@ -345,6 +349,10 @@ type_name ## _get_type (void) { \ * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_INVERT_BOOLEAN, "invert-boolean")) * ]| * + * For projects that have multiple enumeration types, or enumeration + * types with many values, you should consider using glib-mkenums to + * generate the type function. + * * Since: 2.74 */ #define G_DEFINE_FLAGS_TYPE(TypeName, type_name, values) \ From c0766caf20360ce64f648f5fa42bd8f6e7509ac2 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 29 Jun 2022 17:57:32 +0100 Subject: [PATCH 6/7] Use varargs for enum types definition macros Makes the syntax a little bit better. --- gobject/genums.h | 26 +++++++++++++------------- gobject/tests/enums.c | 10 +++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/gobject/genums.h b/gobject/genums.h index 2cd5000f9..a28758a72 100644 --- a/gobject/genums.h +++ b/gobject/genums.h @@ -288,13 +288,13 @@ void g_flags_complete_type_info (GType g_flags_type, * * Since: 2.74 */ -#define G_DEFINE_ENUM_VALUE(EnumValue, EnumNick) { EnumValue, #EnumValue, EnumNick }, +#define G_DEFINE_ENUM_VALUE(EnumValue, EnumNick) { EnumValue, #EnumValue, EnumNick } /** * G_DEFINE_ENUM_TYPE: * @TypeName: the enumeration type, in `CamelCase` * @type_name: the enumeration type prefixed, in `snake_case` - * @values: a list of enumeration values, defined using G_DEFINE_ENUM_VALUE() + * @...: a list of enumeration values, defined using G_DEFINE_ENUM_VALUE() * * A convenience macro for defining enumeration types. * @@ -303,7 +303,7 @@ void g_flags_complete_type_info (GType g_flags_type, * * |[ * G_DEFINE_ENUM_TYPE (GtkOrientation, gtk_orientation, - * G_DEFINE_ENUM_VALUE (GTK_ORIENTATION_HORIZONTAL, "horizontal") + * G_DEFINE_ENUM_VALUE (GTK_ORIENTATION_HORIZONTAL, "horizontal"), * G_DEFINE_ENUM_VALUE (GTK_ORIENTATION_VERTICAL, "vertical")) * ]| * @@ -313,13 +313,13 @@ void g_flags_complete_type_info (GType g_flags_type, * * Since: 2.74 */ -#define G_DEFINE_ENUM_TYPE(TypeName, type_name, values) \ +#define G_DEFINE_ENUM_TYPE(TypeName, type_name, ...) \ GType \ type_name ## _get_type (void) { \ static gsize g_define_type__static = 0; \ if (g_once_init_enter (&g_define_type__static)) { \ static const GEnumValue enum_values[] = { \ - values \ + __VA_ARGS__ , \ { 0, NULL, NULL }, \ }; \ GType g_define_type = g_enum_register_static (g_intern_static_string (#TypeName), enum_values); \ @@ -332,7 +332,7 @@ type_name ## _get_type (void) { \ * G_DEFINE_FLAGS_TYPE: * @TypeName: the enumeration type, in `CamelCase` * @type_name: the enumeration type prefixed, in `snake_case` - * @values: a list of enumeration values, defined using G_DEFINE_ENUM_VALUE() + * @...: a list of enumeration values, defined using G_DEFINE_ENUM_VALUE() * * A convenience macro for defining flag types. * @@ -341,11 +341,11 @@ type_name ## _get_type (void) { \ * * |[ * G_DEFINE_FLAGS_TYPE (GSettingsBindFlags, g_settings_bind_flags, - * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_DEFAULT, "default") - * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_GET, "get") - * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_SET, "set") - * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_NO_SENSITIVITY, "no-sensitivity") - * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_GET_NO_CHANGES, "get-no-changes") + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_DEFAULT, "default"), + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_GET, "get"), + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_SET, "set"), + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_NO_SENSITIVITY, "no-sensitivity"), + * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_GET_NO_CHANGES, "get-no-changes"), * G_DEFINE_ENUM_VALUE (G_SETTINGS_BIND_INVERT_BOOLEAN, "invert-boolean")) * ]| * @@ -355,13 +355,13 @@ type_name ## _get_type (void) { \ * * Since: 2.74 */ -#define G_DEFINE_FLAGS_TYPE(TypeName, type_name, values) \ +#define G_DEFINE_FLAGS_TYPE(TypeName, type_name, ...) \ GType \ type_name ## _get_type (void) { \ static gsize g_define_type__static = 0; \ if (g_once_init_enter (&g_define_type__static)) { \ static const GFlagsValue flags_values[] = { \ - values \ + __VA_ARGS__ , \ { 0, NULL, NULL }, \ }; \ GType g_define_type = g_flags_register_static (g_intern_static_string (#TypeName), flags_values); \ diff --git a/gobject/tests/enums.c b/gobject/tests/enums.c index 0c465172d..9ec1666d0 100644 --- a/gobject/tests/enums.c +++ b/gobject/tests/enums.c @@ -167,8 +167,8 @@ typedef enum { GType test_enum_get_type (void); G_DEFINE_ENUM_TYPE (TestEnum, test_enum, - G_DEFINE_ENUM_VALUE (TEST_ENUM_FIRST_VALUE, "first-value") - G_DEFINE_ENUM_VALUE (TEST_ENUM_SECOND_VALUE, "second-value") + G_DEFINE_ENUM_VALUE (TEST_ENUM_FIRST_VALUE, "first-value"), + G_DEFINE_ENUM_VALUE (TEST_ENUM_SECOND_VALUE, "second-value"), G_DEFINE_ENUM_VALUE (TEST_ENUM_THIRD_VALUE, "third-value")) static void @@ -200,9 +200,9 @@ typedef enum { GType test_flags_get_type (void); G_DEFINE_FLAGS_TYPE (TestFlags, test_flags, - G_DEFINE_ENUM_VALUE (TEST_FLAGS_DEFAULT, "default") - G_DEFINE_ENUM_VALUE (TEST_FLAGS_FIRST, "first") - G_DEFINE_ENUM_VALUE (TEST_FLAGS_SECOND, "second") + G_DEFINE_ENUM_VALUE (TEST_FLAGS_DEFAULT, "default"), + G_DEFINE_ENUM_VALUE (TEST_FLAGS_FIRST, "first"), + G_DEFINE_ENUM_VALUE (TEST_FLAGS_SECOND, "second"), G_DEFINE_ENUM_VALUE (TEST_FLAGS_THIRD, "third")) static void From c4f9b926d8982807fc59e1ce66d20f812338b0d6 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 29 Jun 2022 18:05:16 +0100 Subject: [PATCH 7/7] Add versioning to the new macros They are available in 2.74. --- gobject/genums.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gobject/genums.h b/gobject/genums.h index a28758a72..e54253c20 100644 --- a/gobject/genums.h +++ b/gobject/genums.h @@ -288,7 +288,9 @@ void g_flags_complete_type_info (GType g_flags_type, * * Since: 2.74 */ -#define G_DEFINE_ENUM_VALUE(EnumValue, EnumNick) { EnumValue, #EnumValue, EnumNick } +#define G_DEFINE_ENUM_VALUE(EnumValue, EnumNick) \ + { EnumValue, #EnumValue, EnumNick } \ + GLIB_AVAILABLE_MACRO_IN_2_74 /** * G_DEFINE_ENUM_TYPE: @@ -326,7 +328,8 @@ type_name ## _get_type (void) { \ g_once_init_leave (&g_define_type__static, g_define_type); \ } \ return g_define_type__static; \ -} +} \ + GLIB_AVAILABLE_MACRO_IN_2_74 /** * G_DEFINE_FLAGS_TYPE: @@ -368,7 +371,8 @@ type_name ## _get_type (void) { \ g_once_init_leave (&g_define_type__static, g_define_type); \ } \ return g_define_type__static; \ -} +} \ + GLIB_AVAILABLE_MACRO_IN_2_74 G_END_DECLS