diff --git a/girepository/giarginfo.c b/girepository/giarginfo.c index 6367c22ea..11302d416 100644 --- a/girepository/giarginfo.c +++ b/girepository/giarginfo.c @@ -354,6 +354,9 @@ gi_arg_info_get_type_info (GIArgInfo *info) * * The initialized @type must not be referenced after @info is deallocated. * + * Once you are done with @type, it must be cleared using + * [method@GIRepository.BaseInfo.clear]. + * * Since: 2.80 */ void diff --git a/girepository/gibaseinfo.c b/girepository/gibaseinfo.c index 24ce21f1f..7a12c811f 100644 --- a/girepository/gibaseinfo.c +++ b/girepository/gibaseinfo.c @@ -141,6 +141,9 @@ gi_base_info_class_init (GIBaseInfoClass *klass) static void gi_base_info_init (GIBaseInfo *self) { + /* Initialise a dynamically allocated #GIBaseInfo’s members. + * + * This function *must* be kept in sync with gi_info_init(). */ g_atomic_ref_count_init (&self->ref_count); } @@ -405,6 +408,20 @@ gi_info_init (GIRealInfo *info, { memset (info, 0, sizeof (GIRealInfo)); + /* Evil setup of a stack allocated #GTypeInstance. This is not something it’s + * really designed to do. + * + * This function *must* be kept in sync with gi_base_info_init(), which is + * the equivalent function for dynamically allocated types. */ + info->parent_instance.g_class = g_type_class_ref (type); + + /* g_type_create_instance() calls the #GInstanceInitFunc for each of the + * parent types, down to (and including) @type. We don’t need to do that, as + * #GIBaseInfo is fundamental so doesn’t have a parent type, the instance init + * function for #GIBaseInfo is gi_base_info_init() (which only sets the + * refcount, which we already do here), and subtypes of #GIBaseInfo don’t have + * instance init functions (see gi_base_info_type_register_static()). */ + /* Invalid refcount used to flag stack-allocated infos */ info->ref_count = INVALID_REFCOUNT; info->typelib = typelib; @@ -417,6 +434,34 @@ gi_info_init (GIRealInfo *info, info->repository = repository; } +/** + * gi_base_info_clear: + * @info: (type GIRepository.BaseInfo): a #GIBaseInfo + * + * Clears memory allocated internally by a stack-allocated + * [type@GIRepository.BaseInfo]. + * + * This does not deallocate the [type@GIRepository.BaseInfo] struct itself. + * + * This must only be called on stack-allocated [type@GIRepository.BaseInfo]s. + * Use [method@GIRepository.BaseInfo.unref] for heap-allocated ones. + * + * Since: 2.80 + */ +void +gi_base_info_clear (void *info) +{ + GIBaseInfo *rinfo = (GIBaseInfo *) info; + + g_return_if_fail (GI_IS_BASE_INFO (rinfo)); + + g_assert (rinfo->ref_count == INVALID_REFCOUNT); + + GI_BASE_INFO_GET_CLASS (info)->finalize (rinfo); + + g_type_class_unref (rinfo->parent_instance.g_class); +} + GIBaseInfo * gi_info_from_entry (GIRepository *repository, GITypelib *typelib, @@ -559,6 +604,9 @@ gi_base_info_ref (void *info) * Decreases the reference count of @info. When its reference count * drops to 0, the info is freed. * + * This must not be called on stack-allocated [type@GIRepository.BaseInfo]s — + * use [method@GIRepository.BaseInfo.clear] for that. + * * Since: 2.80 */ void diff --git a/girepository/gibaseinfo.h b/girepository/gibaseinfo.h index 4e152fca6..79969f531 100644 --- a/girepository/gibaseinfo.h +++ b/girepository/gibaseinfo.h @@ -94,6 +94,9 @@ GIBaseInfo * gi_base_info_ref (void *info); GI_AVAILABLE_IN_ALL void gi_base_info_unref (void *info); +GI_AVAILABLE_IN_ALL +void gi_base_info_clear (void *info); + GI_AVAILABLE_IN_ALL GIInfoType gi_base_info_get_info_type (GIBaseInfo *info); diff --git a/girepository/gicallableinfo.c b/girepository/gicallableinfo.c index 9e1fc38aa..1c8c8ef17 100644 --- a/girepository/gicallableinfo.c +++ b/girepository/gicallableinfo.c @@ -201,6 +201,9 @@ gi_callable_info_get_return_type (GICallableInfo *info) * * The initialized @type must not be referenced after @info is deallocated. * + * Once you are done with @type, it must be cleared using + * [method@GIRepository.BaseInfo.clear]. + * * Since: 2.80 */ void @@ -389,6 +392,9 @@ gi_callable_info_get_arg (GICallableInfo *info, * * The initialized @arg must not be referenced after @info is deallocated. * + * Once you are done with @arg, it must be cleared using + * [method@GIRepository.BaseInfo.clear]. + * * Since: 2.80 */ void diff --git a/girepository/girffi.c b/girepository/girffi.c index b9e6ee8b4..107ad42d7 100644 --- a/girepository/girffi.c +++ b/girepository/girffi.c @@ -220,6 +220,9 @@ gi_callable_info_get_ffi_arg_types (GICallableInfo *callable_info, default: g_assert_not_reached (); } + + gi_base_info_clear (&arg_type); + gi_base_info_clear (&arg_info); } arg_types[n_invoke_args] = NULL;