[gobject-introspection] girffi: Fix g_callable_info_prepare_closure for certain callables
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gobject-introspection] girffi: Fix g_callable_info_prepare_closure for certain callables
- Date: Mon, 20 Aug 2012 19:02:16 +0000 (UTC)
commit d8970fbc500a8b20853b564536251315587450d9
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Mon Apr 9 17:51:08 2012 -0300
girffi: Fix g_callable_info_prepare_closure for certain callables
Namely, those that are methods and those that throw GErrors.
We have very similar code in two places that calculate arg lengths and
argument types to stick into libffi. Merge, clean up, and correct both.
https://bugzilla.gnome.org/show_bug.cgi?id=673805
girepository/girffi.c | 115 +++++++++++++++++++------------------------------
1 files changed, 44 insertions(+), 71 deletions(-)
---
diff --git a/girepository/girffi.c b/girepository/girffi.c
index f6e47fb..ec710c3 100644
--- a/girepository/girffi.c
+++ b/girepository/girffi.c
@@ -146,42 +146,65 @@ g_type_info_get_ffi_type (GITypeInfo *info)
/**
* g_callable_info_get_ffi_arg_types:
* @callable_info: a callable info from a typelib
+ * @n_args_p: (out): The number of arguments
*
* Return value: an array of ffi_type*. The array itself
* should be freed using g_free() after use.
*/
static ffi_type **
-g_callable_info_get_ffi_arg_types (GICallableInfo *callable_info)
+g_callable_info_get_ffi_arg_types (GICallableInfo *callable_info,
+ int *n_args_p)
{
ffi_type **arg_types;
- gint n_args, i;
+ gboolean is_method, throws;
+ gint n_args, n_invoke_args, i, offset;
g_return_val_if_fail (callable_info != NULL, NULL);
n_args = g_callable_info_get_n_args (callable_info);
+ is_method = g_callable_info_is_method (callable_info);
+ throws = g_callable_info_can_throw_gerror (callable_info);
+ offset = is_method ? 1 : 0;
- arg_types = (ffi_type **) g_new0 (ffi_type *, n_args + 1);
+ n_invoke_args = n_args;
+
+ if (is_method)
+ n_invoke_args++;
+ if (throws)
+ n_invoke_args++;
+
+ if (n_args_p)
+ *n_args_p = n_invoke_args;
+
+ arg_types = (ffi_type **) g_new0 (ffi_type *, n_invoke_args + 1);
+
+ if (is_method)
+ arg_types[0] = &ffi_type_pointer;
+ if (throws)
+ arg_types[n_invoke_args - 1] = &ffi_type_pointer;
for (i = 0; i < n_args; ++i)
{
- GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
- GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
- switch (g_arg_info_get_direction (arg_info))
+ GIArgInfo arg_info;
+ GITypeInfo arg_type;
+
+ g_callable_info_load_arg (callable_info, i, &arg_info);
+ g_arg_info_load_type (&arg_info, &arg_type);
+ switch (g_arg_info_get_direction (&arg_info))
{
case GI_DIRECTION_IN:
- arg_types[i] = g_type_info_get_ffi_type (arg_type);
+ arg_types[i + offset] = g_type_info_get_ffi_type (&arg_type);
break;
case GI_DIRECTION_OUT:
case GI_DIRECTION_INOUT:
- arg_types[i] = &ffi_type_pointer;
+ arg_types[i + offset] = &ffi_type_pointer;
break;
default:
g_assert_not_reached ();
}
- g_base_info_unref ((GIBaseInfo *)arg_info);
- g_base_info_unref ((GIBaseInfo *)arg_type);
}
- arg_types[n_args] = NULL;
+
+ arg_types[n_invoke_args] = NULL;
return arg_types;
}
@@ -275,71 +298,19 @@ g_function_invoker_new_for_address (gpointer addr,
GIFunctionInvoker *invoker,
GError **error)
{
- ffi_type *rtype;
ffi_type **atypes;
- GITypeInfo *tinfo;
- GIArgInfo *ainfo;
- GIInfoType info_type;
- gboolean is_method;
- gboolean throws;
- gint n_args, n_invoke_args, i;
+ gint n_args;
g_return_val_if_fail (info != NULL, FALSE);
g_return_val_if_fail (invoker != NULL, FALSE);
invoker->native_address = addr;
- is_method = g_callable_info_is_method (info);
- throws = g_callable_info_can_throw_gerror (info);
-
- tinfo = g_callable_info_get_return_type (info);
- rtype = g_type_info_get_ffi_type (tinfo);
- g_base_info_unref ((GIBaseInfo *)tinfo);
-
- n_args = g_callable_info_get_n_args (info);
- if (is_method)
- n_invoke_args = n_args+1;
- else
- n_invoke_args = n_args;
-
- if (throws)
- /* Add an argument for the GError */
- n_invoke_args ++;
-
- /* TODO: avoid malloc here? */
- atypes = g_malloc0 (sizeof (ffi_type*) * n_invoke_args);
+ atypes = g_callable_info_get_ffi_arg_types (info, &n_args);
- if (is_method)
- {
- atypes[0] = &ffi_type_pointer;
- }
- for (i = 0; i < n_args; i++)
- {
- int offset = (is_method ? 1 : 0);
- ainfo = g_callable_info_get_arg (info, i);
- switch (g_arg_info_get_direction (ainfo))
- {
- case GI_DIRECTION_IN:
- tinfo = g_arg_info_get_type (ainfo);
- atypes[i+offset] = g_type_info_get_ffi_type (tinfo);
- g_base_info_unref ((GIBaseInfo *)tinfo);
- break;
- case GI_DIRECTION_OUT:
- case GI_DIRECTION_INOUT:
- atypes[i+offset] = &ffi_type_pointer;
- break;
- default:
- g_assert_not_reached ();
- }
- g_base_info_unref ((GIBaseInfo *)ainfo);
- }
-
- if (throws)
- {
- atypes[n_invoke_args - 1] = &ffi_type_pointer;
- }
-
- return ffi_prep_cif (&(invoker->cif), FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) == FFI_OK;
+ return ffi_prep_cif (&(invoker->cif), FFI_DEFAULT_ABI, n_args,
+ g_callable_info_get_ffi_return_type (info),
+ atypes) == FFI_OK;
}
/**
@@ -380,6 +351,8 @@ g_callable_info_prepare_closure (GICallableInfo *callable_info,
gpointer user_data)
{
gpointer exec_ptr;
+ int n_args;
+ ffi_type **atypes;
GIClosureWrapper *closure;
ffi_status status;
@@ -395,10 +368,10 @@ g_callable_info_prepare_closure (GICallableInfo *callable_info,
}
closure->writable_self = closure;
- status = ffi_prep_cif (cif, FFI_DEFAULT_ABI,
- g_callable_info_get_n_args (callable_info),
+ atypes = g_callable_info_get_ffi_arg_types (callable_info, &n_args);
+ status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, n_args,
g_callable_info_get_ffi_return_type (callable_info),
- g_callable_info_get_ffi_arg_types (callable_info));
+ atypes);
if (status != FFI_OK)
{
g_warning ("ffi_prep_cif failed: %d\n", status);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]