girepository: add singleton GIRepository back

This is needed to avoid situations where you cannot coordinate between
bindings and libraries which also need to interact with introspection
which could affect bindings.

For example, a Python application using libpeas to load plugins, also in
Python.

Fixes: #3664
This commit is contained in:
Christian Hergert
2025-05-11 15:25:06 -07:00
parent 314d63fcf7
commit 690ba3b7b5
3 changed files with 48 additions and 0 deletions

View File

@@ -2271,3 +2271,33 @@ gi_typelib_blob_type_to_info_type (GITypelibBlobType blob_type)
return (GIInfoType) blob_type;
}
}
/**
* gi_repository_dup_default:
*
* Gets the singleton process-global default `GIRepository`.
*
* The singleton is needed for situations where you must coordinate between
* bindings and libraries which also need to interact with introspection which
* could affect the bindings. For example, a Python application using a
* GObject-based library through `GIRepository` to load plugins also written in
* Python.
*
* Returns: (transfer full): the global singleton repository
*
* Since: 2.86
*/
GIRepository *
gi_repository_dup_default (void)
{
static GIRepository *instance;
if (g_once_init_enter (&instance))
{
GIRepository *repository = gi_repository_new ();
g_object_add_weak_pointer (G_OBJECT (repository), (gpointer *)&instance);
g_once_init_leave (&instance, repository);
}
return g_object_ref (instance);
}

View File

@@ -242,6 +242,9 @@ void gi_cclosure_marshal_generic (GClosure *closure,
void *invocation_hint,
void *marshal_data);
GI_AVAILABLE_IN_2_86
GIRepository *gi_repository_dup_default (void);
#include <girepository/girepository-autocleanups.h>
G_END_DECLS

View File

@@ -895,6 +895,20 @@ test_repository_loaded_namespaces (RepositoryFixture *fx,
g_strfreev (namespaces);
}
static void
test_repository_dup_default (void)
{
GIRepository *repository1 = gi_repository_dup_default ();
GIRepository *repository2 = gi_repository_dup_default ();
g_assert_nonnull (repository1);
g_assert_nonnull (repository2);
g_assert_true (repository1 == repository2);
g_clear_object (&repository1);
g_clear_object (&repository2);
}
int
main (int argc,
char *argv[])
@@ -924,6 +938,7 @@ main (int argc,
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-invoker-on-object", test_repository_vfunc_info_with_invoker_on_object, &typelib_load_spec_gio);
ADD_REPOSITORY_TEST ("/repository/find-by-gtype", test_repository_find_by_gtype, &typelib_load_spec_gio_platform);
ADD_REPOSITORY_TEST ("/repository/loaded-namespaces", test_repository_loaded_namespaces, &typelib_load_spec_gio_platform);
g_test_add_func ("/repository/dup_default", test_repository_dup_default);
return g_test_run ();
}