summaryrefslogtreecommitdiff
path: root/girepository/gifunctioninfo.c
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu.vizoso@collabora.co.uk>2010-12-13 13:53:55 +0100
committerTomeu Vizoso <tomeu.vizoso@collabora.co.uk>2011-01-12 20:05:09 +0100
commit0c3a1d82f2543b74468d1806f87aa0cb258a925d (patch)
treed7919bfab9e8e03599468939852bff69ed50f97d /girepository/gifunctioninfo.c
parent36e79f8d485bb670ac53be52ff3962f9e157dc42 (diff)
downloadgobject-introspection-0c3a1d82f2543b74468d1806f87aa0cb258a925d.tar.gz
Add g_vfunc_info_invoke and g_vfunc_info_get_address
for calling the native implementation of a virtual function. Refactors the code common with g_function_info_invoke in _g_callable_info_invoke. https://bugzilla.gnome.org/show_bug.cgi?id=637145
Diffstat (limited to 'girepository/gifunctioninfo.c')
-rw-r--r--girepository/gifunctioninfo.c167
1 files changed, 10 insertions, 157 deletions
diff --git a/girepository/gifunctioninfo.c b/girepository/gifunctioninfo.c
index 2f8920de..2544cc3f 100644
--- a/girepository/gifunctioninfo.c
+++ b/girepository/gifunctioninfo.c
@@ -26,7 +26,6 @@
#include <girepository.h>
#include "girepository-private.h"
#include "gitypelib-internal.h"
-#include "girffi.h"
/**
* SECTION:gifunctioninfo
@@ -249,20 +248,10 @@ g_function_info_invoke (GIFunctionInfo *info,
GIArgument *return_value,
GError **error)
{
- ffi_cif cif;
- ffi_type *rtype;
- ffi_type **atypes;
const gchar *symbol;
gpointer func;
- GITypeInfo *tinfo;
- GIArgInfo *ainfo;
gboolean is_method;
gboolean throws;
- gint n_args, n_invoke_args, in_pos, out_pos, i;
- gpointer *args;
- gboolean success = FALSE;
- GError *local_error = NULL;
- gpointer error_address = &local_error;
symbol = g_function_info_get_symbol (info);
@@ -281,150 +270,14 @@ g_function_info_invoke (GIFunctionInfo *info,
&& (g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0;
throws = g_function_info_get_flags (info) & GI_FUNCTION_THROWS;
- tinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
- rtype = g_type_info_get_ffi_type (tinfo);
- g_base_info_unref ((GIBaseInfo *)tinfo);
-
- in_pos = 0;
- out_pos = 0;
-
- n_args = g_callable_info_get_n_args ((GICallableInfo *)info);
- if (is_method)
- {
- if (n_in_args == 0)
- {
- g_set_error (error,
- G_INVOKE_ERROR,
- G_INVOKE_ERROR_ARGUMENT_MISMATCH,
- "Too few \"in\" arguments (handling this)");
- goto out;
- }
- n_invoke_args = n_args+1;
- in_pos++;
- }
- else
- n_invoke_args = n_args;
-
- if (throws)
- /* Add an argument for the GError */
- n_invoke_args ++;
-
- atypes = g_alloca (sizeof (ffi_type*) * n_invoke_args);
- args = g_alloca (sizeof (gpointer) * n_invoke_args);
-
- if (is_method)
- {
- atypes[0] = &ffi_type_pointer;
- args[0] = (gpointer) &in_args[0];
- }
- for (i = 0; i < n_args; i++)
- {
- int offset = (is_method ? 1 : 0);
- ainfo = g_callable_info_get_arg ((GICallableInfo *)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);
-
- if (in_pos >= n_in_args)
- {
- g_set_error (error,
- G_INVOKE_ERROR,
- G_INVOKE_ERROR_ARGUMENT_MISMATCH,
- "Too few \"in\" arguments (handling in)");
- goto out;
- }
-
- args[i+offset] = (gpointer)&in_args[in_pos];
- in_pos++;
-
- break;
- case GI_DIRECTION_OUT:
- atypes[i+offset] = &ffi_type_pointer;
-
- if (out_pos >= n_out_args)
- {
- g_set_error (error,
- G_INVOKE_ERROR,
- G_INVOKE_ERROR_ARGUMENT_MISMATCH,
- "Too few \"out\" arguments (handling out)");
- goto out;
- }
-
- args[i+offset] = (gpointer)&out_args[out_pos];
- out_pos++;
- break;
- case GI_DIRECTION_INOUT:
- atypes[i+offset] = &ffi_type_pointer;
-
- if (in_pos >= n_in_args)
- {
- g_set_error (error,
- G_INVOKE_ERROR,
- G_INVOKE_ERROR_ARGUMENT_MISMATCH,
- "Too few \"in\" arguments (handling inout)");
- goto out;
- }
-
- if (out_pos >= n_out_args)
- {
- g_set_error (error,
- G_INVOKE_ERROR,
- G_INVOKE_ERROR_ARGUMENT_MISMATCH,
- "Too few \"out\" arguments (handling inout)");
- goto out;
- }
-
- args[i+offset] = (gpointer)&in_args[in_pos];
- in_pos++;
- out_pos++;
- break;
- default:
- g_assert_not_reached ();
- }
- g_base_info_unref ((GIBaseInfo *)ainfo);
- }
-
- if (throws)
- {
- args[n_invoke_args - 1] = &error_address;
- atypes[n_invoke_args - 1] = &ffi_type_pointer;
- }
-
- if (in_pos < n_in_args)
- {
- g_set_error (error,
- G_INVOKE_ERROR,
- G_INVOKE_ERROR_ARGUMENT_MISMATCH,
- "Too many \"in\" arguments (at end)");
- goto out;
- }
- if (out_pos < n_out_args)
- {
- g_set_error (error,
- G_INVOKE_ERROR,
- G_INVOKE_ERROR_ARGUMENT_MISMATCH,
- "Too many \"out\" arguments (at end)");
- goto out;
- }
-
- if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) != FFI_OK)
- goto out;
-
- g_return_val_if_fail (return_value, FALSE);
- ffi_call (&cif, func, return_value, args);
-
- if (local_error)
- {
- g_propagate_error (error, local_error);
- success = FALSE;
- }
- else
- {
- success = TRUE;
- }
- out:
- return success;
+ return _g_callable_info_invoke ((GICallableInfo*) info,
+ func,
+ in_args,
+ n_in_args,
+ out_args,
+ n_out_args,
+ return_value,
+ is_method,
+ throws,
+ error);
}