Merge branch 'gi-static-vfuncs' into 'main'

Support static vfuncs in GIRepository

See merge request GNOME/glib!4457
This commit is contained in:
Michael Catanzaro 2025-02-01 14:10:57 +00:00
commit 9b1e0a583a
6 changed files with 112 additions and 4 deletions

View File

@ -135,9 +135,12 @@ gi_callable_info_can_throw_gerror (GICallableInfo *info)
*
* Determines if the callable info is a method.
*
* For [class@GIRepository.VFuncInfo]s, [class@GIRepository.CallbackInfo]s, and
* [class@GIRepository.SignalInfo]s, this is always true. Otherwise, this looks
* at the `GI_FUNCTION_IS_METHOD` flag on the [class@GIRepository.FunctionInfo].
* For [class@GIRepository.SignalInfo]s, this is always true, and for
* [class@GIRepository.CallbackInfo]s always false.
* For [class@GIRepository.FunctionInfo]s this looks at the
* `GI_FUNCTION_IS_METHOD` flag on the [class@GIRepository.FunctionInfo].
* For [class@GIRepository.VFuncInfo]s this is true when the virtual function
* has an instance parameter.
*
* Concretely, this function returns whether
* [method@GIRepository.CallableInfo.get_n_args] matches the number of arguments
@ -159,6 +162,11 @@ gi_callable_info_is_method (GICallableInfo *info)
return (!blob->constructor && !blob->is_static);
}
case GI_INFO_TYPE_VFUNC:
{
VFuncBlob *blob;
blob = (VFuncBlob *) &rinfo->typelib->data[rinfo->offset];
return !blob->is_static;
}
case GI_INFO_TYPE_SIGNAL:
return TRUE;
case GI_INFO_TYPE_CALLBACK:

View File

@ -243,6 +243,8 @@ struct _GIIrNodeVFunc
uint8_t instance_transfer_full : 1;
uint8_t is_async : 1;
uint8_t is_static : 1;
char *invoker; /* (owned) */
char *finish_func; /* (owned) */
char *sync_func; /* (owned) */

View File

@ -2029,6 +2029,7 @@ gi_ir_node_build_typelib (GIIrNode *node,
blob->struct_offset = vfunc->offset;
blob->reserved2 = 0;
blob->signature = signature;
blob->is_static = vfunc->is_static;
gi_ir_node_build_typelib ((GIIrNode *)vfunc->result->type,
node, build, &signature, offset2, NULL);

View File

@ -2660,6 +2660,7 @@ start_vfunc (GMarkupParseContext *context,
const char *offset;
const char *invoker;
const char *throws;
const char *is_static;
const char *finish_func;
const char *async_func;
const char *sync_func;
@ -2682,6 +2683,7 @@ start_vfunc (GMarkupParseContext *context,
offset = find_attribute ("offset", attribute_names, attribute_values);
invoker = find_attribute ("invoker", attribute_names, attribute_values);
throws = find_attribute ("throws", attribute_names, attribute_values);
is_static = find_attribute ("glib:static", attribute_names, attribute_values);
finish_func = find_attribute ("glib:finish-func", attribute_names, attribute_values);
sync_func = find_attribute ("glib:sync-func", attribute_names, attribute_values);
async_func = find_attribute ("glib:async-func", attribute_names, attribute_values);
@ -2728,6 +2730,11 @@ start_vfunc (GMarkupParseContext *context,
else
vfunc->throws = FALSE;
if (is_static && strcmp (is_static, "1") == 0)
vfunc->is_static = TRUE;
else
vfunc->is_static = FALSE;
if (offset == NULL)
vfunc->offset = 0xFFFF;
else if (g_ascii_string_to_unsigned (offset, 10, 0, G_MAXSIZE, &parsed_offset, error))

View File

@ -1117,6 +1117,7 @@ typedef struct {
* @invoker: If a method invoker for this virtual exists, this is the offset
* in the class structure of the method. If no method is known, this value
* will be 0x3ff.
* @is_static: True if the vfunc has no instance parameter.
* @reserved: Reserved for future use.
* @finish: The index of the finish function if is_async is TRUE, otherwise ASYNC_SENTINEL
* @reserved2: Reserved for future use.
@ -1142,7 +1143,8 @@ typedef struct {
uint16_t struct_offset;
uint16_t invoker : 10; /* Number of bits matches @index in FunctionBlob */
uint16_t reserved : 6;
uint16_t is_static : 1;
uint16_t reserved : 5;
uint16_t finish : 10;
uint16_t reserved2 : 6;

View File

@ -124,6 +124,91 @@ test_callable_get_async_function_for_sync_function (RepositoryFixture *fx,
gi_base_info_unref (info);
}
static void
test_callable_info_is_method (RepositoryFixture *fx,
const void *unused)
{
GIBaseInfo *info;
GIFunctionInfo *func_info;
GIVFuncInfo *vfunc_info;
GISignalInfo *sig_info;
GIBaseInfo *cb_info;
info = gi_repository_find_by_name (fx->repository, "Gio", "ActionGroup");
g_assert_nonnull (info);
func_info = gi_interface_info_find_method (GI_INTERFACE_INFO (info), "action_added");
g_assert_nonnull (func_info);
g_assert_true (gi_callable_info_is_method (GI_CALLABLE_INFO (func_info)));
vfunc_info = gi_interface_info_find_vfunc (GI_INTERFACE_INFO (info), "action_added");
g_assert_nonnull (vfunc_info);
g_assert_true (gi_callable_info_is_method (GI_CALLABLE_INFO (vfunc_info)));
sig_info = gi_interface_info_find_signal (GI_INTERFACE_INFO (info), "action-added");
g_assert_nonnull (sig_info);
g_assert_true (gi_callable_info_is_method (GI_CALLABLE_INFO (sig_info)));
cb_info = gi_repository_find_by_name (fx->repository, "Gio", "AsyncReadyCallback");
g_assert_nonnull (cb_info);
g_assert_false (gi_callable_info_is_method (GI_CALLABLE_INFO (cb_info)));
gi_base_info_unref (info);
gi_base_info_unref ((GIBaseInfo *) func_info);
gi_base_info_unref ((GIBaseInfo *) vfunc_info);
gi_base_info_unref ((GIBaseInfo *) sig_info);
gi_base_info_unref (cb_info);
}
static void
test_callable_info_static_method (RepositoryFixture *fx,
const void *unused)
{
GIBaseInfo *info;
GIFunctionInfo *func_info;
info = gi_repository_find_by_name (fx->repository, "Gio", "Application");
g_assert_nonnull (info);
func_info = gi_object_info_find_method (GI_OBJECT_INFO (info), "get_default");
g_assert_nonnull (func_info);
g_assert_false (gi_callable_info_is_method (GI_CALLABLE_INFO (func_info)));
gi_base_info_unref (info);
gi_base_info_unref ((GIBaseInfo *) func_info);
}
static void
test_callable_info_static_vfunc (RepositoryFixture *fx,
const void *unused)
{
GIBaseInfo *info;
GIVFuncInfo *vfunc_info;
g_test_bug ("https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/361");
info = gi_repository_find_by_name (fx->repository, "Gio", "Icon");
g_assert_nonnull (info);
vfunc_info = gi_interface_info_find_vfunc (GI_INTERFACE_INFO (info), "from_tokens");
if (!vfunc_info)
{
g_test_skip ("g-ir-scanner is not new enough");
return;
}
g_assert_nonnull (vfunc_info);
g_assert_false (gi_callable_info_is_method (GI_CALLABLE_INFO (vfunc_info)));
gi_base_info_unref (info);
gi_base_info_unref ((GIBaseInfo *) vfunc_info);
}
int
main (int argc, char **argv)
{
@ -131,6 +216,9 @@ main (int argc, char **argv)
ADD_REPOSITORY_TEST ("/callable-info/sync-function", test_callable_get_sync_function_for_async_function, &typelib_load_spec_gio);
ADD_REPOSITORY_TEST ("/callable-info/async-function", test_callable_get_async_function_for_sync_function, &typelib_load_spec_gio);
ADD_REPOSITORY_TEST ("/callable-info/is-method", test_callable_info_is_method, &typelib_load_spec_gio);
ADD_REPOSITORY_TEST ("/callable-info/static-method", test_callable_info_static_method, &typelib_load_spec_gio);
ADD_REPOSITORY_TEST ("/callable-info/static-vfunc", test_callable_info_static_vfunc, &typelib_load_spec_gio);
return g_test_run ();
}