[pygi] One more step at refactoring _wrap_g_function_info_invoke



commit 64fa8f936bad9a90628df446e690d67d947a0a22
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date:   Mon Apr 26 11:41:06 2010 +0200

    One more step at refactoring _wrap_g_function_info_invoke
    
    https://bugzilla.gnome.org/show_bug.cgi?id=616357

 gi/pygi-callbacks.c |   22 +-
 gi/pygi-callbacks.h |    4 +-
 gi/pygi-info.c      |  582 +++++++++++++++++++++++++++++----------------------
 3 files changed, 346 insertions(+), 262 deletions(-)
---
diff --git a/gi/pygi-callbacks.c b/gi/pygi-callbacks.c
index fb852ff..7f5de9b 100644
--- a/gi/pygi-callbacks.c
+++ b/gi/pygi-callbacks.c
@@ -64,7 +64,7 @@ _pygi_destroy_notify_create(void)
 
 
 gboolean
-_pygi_scan_for_callbacks (PyGIBaseInfo  *function_info,
+_pygi_scan_for_callbacks (GIFunctionInfo *function_info,
                           gboolean       is_method,
                           guint8        *callback_index,
                           guint8        *user_data_index,
@@ -76,7 +76,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo  *function_info,
     *user_data_index = G_MAXUINT8;
     *destroy_notify_index = G_MAXUINT8;
 
-    n_args = g_callable_info_get_n_args((GICallableInfo *)function_info->info);
+    n_args = g_callable_info_get_n_args((GICallableInfo *)function_info);
     for (i = 0; i < n_args; i++) {
         GIDirection direction;
         GIArgInfo *arg_info;
@@ -84,7 +84,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo  *function_info,
         guint8 destroy, closure;
         GITypeTag type_tag;
 
-        arg_info = g_callable_info_get_arg((GICallableInfo*) function_info->info, i);
+        arg_info = g_callable_info_get_arg((GICallableInfo*) function_info, i);
         type_info = g_arg_info_get_type(arg_info);
         type_tag = g_type_info_get_tag(type_info);    
 
@@ -99,8 +99,8 @@ _pygi_scan_for_callbacks (PyGIBaseInfo  *function_info,
                   strcmp(g_base_info_get_name((GIBaseInfo*) interface_info), "DestroyNotify") == 0)) {
                 if (*callback_index != G_MAXUINT8) {
                     PyErr_Format(PyExc_TypeError, "Function %s.%s has multiple callbacks, not supported",
-                              g_base_info_get_namespace((GIBaseInfo*) function_info->info),
-                              g_base_info_get_name((GIBaseInfo*) function_info->info));
+                              g_base_info_get_namespace((GIBaseInfo*) function_info),
+                              g_base_info_get_name((GIBaseInfo*) function_info));
                     g_base_info_unref(interface_info);
                     return FALSE;
                 }
@@ -119,7 +119,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo  *function_info,
         if (destroy > 0 && destroy < n_args) {
             if (*destroy_notify_index != G_MAXUINT8) {
                 PyErr_Format(PyExc_TypeError, "Function %s has multiple GDestroyNotify, not supported",
-                             g_base_info_get_name((GIBaseInfo*)function_info->info));
+                             g_base_info_get_name((GIBaseInfo*)function_info));
                 return FALSE;
             }
             *destroy_notify_index = destroy;
@@ -128,7 +128,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo  *function_info,
         if (closure > 0 && closure < n_args) {
             if (*user_data_index != G_MAXUINT8) {
                  PyErr_Format(PyExc_TypeError, "Function %s has multiple user_data arguments, not supported",
-                          g_base_info_get_name((GIBaseInfo*)function_info->info));
+                          g_base_info_get_name((GIBaseInfo*)function_info));
                 return FALSE;
             }
             *user_data_index = closure;
@@ -142,7 +142,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo  *function_info,
 }
 
 gboolean
-_pygi_create_callback (PyGIBaseInfo  *function_info,
+_pygi_create_callback (GIBaseInfo  *function_info,
                         gboolean       is_method,
                         int            n_args,
                         Py_ssize_t     py_argc,
@@ -161,7 +161,7 @@ _pygi_create_callback (PyGIBaseInfo  *function_info,
     guint8 i, py_argv_pos;
     PyObject *py_user_data;
 
-    callback_arg = g_callable_info_get_arg((GICallableInfo*) function_info->info, callback_index);
+    callback_arg = g_callable_info_get_arg((GICallableInfo*) function_info, callback_index);
     scope = g_arg_info_get_scope(callback_arg);
 
     callback_type = g_arg_info_get_type(callback_arg);
@@ -194,8 +194,8 @@ _pygi_create_callback (PyGIBaseInfo  *function_info,
     if (!found_py_function
         || (py_function == Py_None || !PyCallable_Check(py_function))) {
         PyErr_Format(PyExc_TypeError, "Error invoking %s.%s: Invalid callback given for argument %s",
-                  g_base_info_get_namespace((GIBaseInfo*) function_info->info),
-                  g_base_info_get_name((GIBaseInfo*) function_info->info),
+                  g_base_info_get_namespace((GIBaseInfo*) function_info),
+                  g_base_info_get_name((GIBaseInfo*) function_info),
                   g_base_info_get_name((GIBaseInfo*) callback_arg));
         g_base_info_unref((GIBaseInfo*) callback_info);
         g_base_info_unref((GIBaseInfo*) callback_type);
diff --git a/gi/pygi-callbacks.h b/gi/pygi-callbacks.h
index 7b3401d..4b98e3d 100644
--- a/gi/pygi-callbacks.h
+++ b/gi/pygi-callbacks.h
@@ -26,13 +26,13 @@ void _pygi_callback_notify_info_free(gpointer user_data);
  
 PyGICClosure*_pygi_destroy_notify_create(void);
 
-gboolean _pygi_scan_for_callbacks (PyGIBaseInfo  *self,
+gboolean _pygi_scan_for_callbacks (GIFunctionInfo *self,
                                    gboolean       is_method,
                                    guint8        *callback_index,
                                    guint8        *user_data_index,
                                    guint8        *destroy_notify_index);
 
-gboolean _pygi_create_callback (PyGIBaseInfo  *self,
+gboolean _pygi_create_callback (GIFunctionInfo *self,
                                 gboolean       is_method,
                                 int            n_args,
                                 Py_ssize_t     py_argc,
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 134a31d..44ab832 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -524,99 +524,105 @@ struct invocation_state
     PyObject *return_value;
 };
 
-
-static PyObject *
-_wrap_g_function_info_invoke (PyGIBaseInfo *self,
-                              PyObject     *py_args)
+static void
+_initialize_invocation_state (struct invocation_state *state,
+                              GIFunctionInfo *info,
+                              PyObject *py_args)
 {
-    struct invocation_state s;
-    gsize i;
-  
-    s.return_value = NULL;
-    s.closure = NULL;
-
-    {
-        GIFunctionInfoFlags flags;
+    GIFunctionInfoFlags flags;
 
-        flags = g_function_info_get_flags((GIFunctionInfo *)self->info);
-        s.is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
-        s.is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
-    }
+    flags = g_function_info_get_flags(info);
+    state->is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
+    state->is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
 
     /* Count arguments. */
-    s.n_args = g_callable_info_get_n_args((GICallableInfo *)self->info);
-    s.n_in_args = 0;
-    s.n_out_args = 0;
-    s.n_backup_args = 0;
-    s.n_aux_in_args = 0;
-    s.n_aux_out_args = 0;
+    state->n_args = g_callable_info_get_n_args((GICallableInfo *)info);
+    state->n_in_args = 0;
+    state->n_out_args = 0;
+    state->n_backup_args = 0;
+    state->n_aux_in_args = 0;
+    state->n_aux_out_args = 0;
     
     /* Check the argument count. */
-    s.n_py_args = PyTuple_Size(py_args);
-    g_assert(s.n_py_args >= 0);
-
-    s.error_arg_pos = -1;
-
-    s.arg_infos = g_newa(GIArgInfo *, s.n_args);
-    s.arg_type_infos = g_newa(GITypeInfo *, s.n_args);
+    state->n_py_args = PyTuple_Size(py_args);
+    g_assert(state->n_py_args >= 0);
+
+    state->error_arg_pos = -1;
+
+    state->arg_infos = g_slice_alloc0(sizeof(gpointer) * state->n_args);
+    state->arg_type_infos = g_slice_alloc0(sizeof(gpointer) * state->n_args);
+    state->args_is_auxiliary = g_slice_alloc0(sizeof(gboolean) * state->n_args);
+
+    state->return_value = NULL;
+    state->closure = NULL;
+    state->return_type_info = NULL;
+    state->args = NULL;
+    state->in_args = NULL;
+    state->out_args = NULL;
+    state->out_values = NULL;
+    state->backup_args = NULL;
+}
 
-    s.args_is_auxiliary = g_newa(gboolean, s.n_args);
-    memset(s.args_is_auxiliary, 0, sizeof(s.args_is_auxiliary) * s.n_args);
+static gboolean
+_prepare_invocation_state (struct invocation_state *state,
+                           GIFunctionInfo *function_info, PyObject *py_args)
+{
+    gsize i;
 
-    if (!_pygi_scan_for_callbacks (self, s.is_method,
-                                   &s.callback_index, &s.user_data_index,
-                                   &s.destroy_notify_index))
-        return NULL;
+    if (!_pygi_scan_for_callbacks (function_info, state->is_method,
+                                   &state->callback_index, &state->user_data_index,
+                                   &state->destroy_notify_index))
+        return FALSE;
         
-    if (s.callback_index != G_MAXUINT8) {
-        if (!_pygi_create_callback (self, s.is_method, 
-                                    s.n_args, s.n_py_args, 
-                                    py_args, s.callback_index,
-                                    s.user_data_index,
-                                    s.destroy_notify_index, &s.closure))
-            return NULL;
-
-        s.args_is_auxiliary[s.callback_index] = FALSE;
-        if (s.destroy_notify_index != G_MAXUINT8) {
-            s.args_is_auxiliary[s.destroy_notify_index] = TRUE;
-            s.n_aux_in_args += 1;
+    if (state->callback_index != G_MAXUINT8) {
+        if (!_pygi_create_callback (function_info, state->is_method, 
+                                    state->n_args, state->n_py_args, 
+                                    py_args, state->callback_index,
+                                    state->user_data_index,
+                                    state->destroy_notify_index, &state->closure))
+            return FALSE;
+
+        state->args_is_auxiliary[state->callback_index] = FALSE;
+        if (state->destroy_notify_index != G_MAXUINT8) {
+            state->args_is_auxiliary[state->destroy_notify_index] = TRUE;
+            state->n_aux_in_args += 1;
         }
     }
 
-    if (s.is_method) {
+    if (state->is_method) {
         /* The first argument is the instance. */
-        s.n_in_args += 1;
+        state->n_in_args += 1;
     }
 
     /* We do a first (well, second) pass here over the function to scan for special cases.
      * This is currently array+length combinations and GError.
      */
-    for (i = 0; i < s.n_args; i++) {
+    for (i = 0; i < state->n_args; i++) {
         GIDirection direction;
         GITransfer transfer;
         GITypeTag arg_type_tag;
         
-        s.arg_infos[i] = g_callable_info_get_arg((GICallableInfo *)self->info,
+        state->arg_infos[i] = g_callable_info_get_arg((GICallableInfo *)function_info,
                                                  i);
 
-        s.arg_type_infos[i] = g_arg_info_get_type(s.arg_infos[i]);
+        state->arg_type_infos[i] = g_arg_info_get_type(state->arg_infos[i]);
         
-        direction = g_arg_info_get_direction(s.arg_infos[i]);
-        transfer = g_arg_info_get_ownership_transfer(s.arg_infos[i]);
-        arg_type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+        direction = g_arg_info_get_direction(state->arg_infos[i]);
+        transfer = g_arg_info_get_ownership_transfer(state->arg_infos[i]);
+        arg_type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
 
         if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
-            s.n_in_args += 1;
+            state->n_in_args += 1;
             if (transfer == GI_TRANSFER_CONTAINER) {
-                s.n_backup_args += 1;
+                state->n_backup_args += 1;
             }
         }
         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
-            s.n_out_args += 1;
+            state->n_out_args += 1;
         }
 
         if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) {
-            s.n_backup_args += 1;
+            state->n_backup_args += 1;
         }
 
         switch (arg_type_tag) {
@@ -624,159 +630,159 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
             {
                 gint length_arg_pos;
 
-                length_arg_pos = g_type_info_get_array_length(s.arg_type_infos[i]);
+                length_arg_pos = g_type_info_get_array_length(state->arg_type_infos[i]);
 
-                if (s.is_method)
+                if (state->is_method)
                     length_arg_pos--; // length_arg_pos refers to C args
 
                 if (length_arg_pos < 0) {
                     break;
                 }
 
-                g_assert(length_arg_pos < s.n_args);
-                s.args_is_auxiliary[length_arg_pos] = TRUE;
+                g_assert(length_arg_pos < state->n_args);
+                state->args_is_auxiliary[length_arg_pos] = TRUE;
 
                 if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
-                    s.n_aux_in_args += 1;
+                    state->n_aux_in_args += 1;
                 }
                 if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
-                    s.n_aux_out_args += 1;
+                    state->n_aux_out_args += 1;
                 }
 
                 break;
             }
             case GI_TYPE_TAG_ERROR:
-                g_warn_if_fail(s.error_arg_pos < 0);
-                s.error_arg_pos = i;
+                g_warn_if_fail(state->error_arg_pos < 0);
+                state->error_arg_pos = i;
                 break;
             default:
                 break;
         }
     }
 
-    s.return_type_info = g_callable_info_get_return_type((GICallableInfo *)self->info);
-    s.return_type_tag = g_type_info_get_tag(s.return_type_info);
+    state->return_type_info = g_callable_info_get_return_type((GICallableInfo *)function_info);
+    state->return_type_tag = g_type_info_get_tag(state->return_type_info);
 
-    if (s.return_type_tag == GI_TYPE_TAG_ARRAY) {
+    if (state->return_type_tag == GI_TYPE_TAG_ARRAY) {
         gint length_arg_pos;
-        length_arg_pos = g_type_info_get_array_length(s.return_type_info);
+        length_arg_pos = g_type_info_get_array_length(state->return_type_info);
 
-        if (s.is_method)
+        if (state->is_method)
             length_arg_pos--; // length_arg_pos refers to C args
 
         if (length_arg_pos >= 0) {
-            g_assert(length_arg_pos < s.n_args);
-            s.args_is_auxiliary[length_arg_pos] = TRUE;
-            s.n_aux_out_args += 1;
+            g_assert(length_arg_pos < state->n_args);
+            state->args_is_auxiliary[length_arg_pos] = TRUE;
+            state->n_aux_out_args += 1;
         }
     }
 
-    s.n_return_values = s.n_out_args - s.n_aux_out_args;
-    if (s.return_type_tag != GI_TYPE_TAG_VOID) {
-        s.n_return_values += 1;
+    state->n_return_values = state->n_out_args - state->n_aux_out_args;
+    if (state->return_type_tag != GI_TYPE_TAG_VOID) {
+        state->n_return_values += 1;
     }
 
     {
         gsize n_py_args_expected;
         Py_ssize_t py_args_pos;
 
-        n_py_args_expected = s.n_in_args
-            + (s.is_constructor ? 1 : 0)
-            - s.n_aux_in_args
-            - (s.error_arg_pos >= 0 ? 1 : 0);
+        n_py_args_expected = state->n_in_args
+            + (state->is_constructor ? 1 : 0)
+            - state->n_aux_in_args
+            - (state->error_arg_pos >= 0 ? 1 : 0);
 
-        if (s.n_py_args != n_py_args_expected) {
+        if (state->n_py_args != n_py_args_expected) {
             PyErr_Format(PyExc_TypeError,
                 "takes exactly %zd argument(s) (%zd given)",
-                n_py_args_expected, s.n_py_args);
-            goto out;
+                n_py_args_expected, state->n_py_args);
+            return FALSE;
         }
 
-        /* Check argument types. */
+        /* Check argument typestate-> */
         py_args_pos = 0;
-        if (s.is_constructor || s.is_method) {
+        if (state->is_constructor || state->is_method) {
             py_args_pos += 1;
         }
 
-        for (i = 0; i < s.n_args; i++) {
+        for (i = 0; i < state->n_args; i++) {
             GIDirection direction;
             GITypeTag type_tag;
             PyObject *py_arg;
             gint retval;
             gboolean allow_none;
 
-            direction = g_arg_info_get_direction(s.arg_infos[i]);
-            type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+            direction = g_arg_info_get_direction(state->arg_infos[i]);
+            type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
 
             if (direction == GI_DIRECTION_OUT
-                    || s.args_is_auxiliary[i]
+                    || state->args_is_auxiliary[i]
                     || type_tag == GI_TYPE_TAG_ERROR) {
                 continue;
             }
 
-            g_assert(py_args_pos < s.n_py_args);
+            g_assert(py_args_pos < state->n_py_args);
             py_arg = PyTuple_GET_ITEM(py_args, py_args_pos);
 
-            allow_none = g_arg_info_may_be_null(s.arg_infos[i]);
+            allow_none = g_arg_info_may_be_null(state->arg_infos[i]);
 
-            retval = _pygi_g_type_info_check_object(s.arg_type_infos[i],
+            retval = _pygi_g_type_info_check_object(state->arg_type_infos[i],
                                                     py_arg,
                                                     allow_none);
 
             if (retval < 0) {
-                goto out;
+                return FALSE;
             } else if (!retval) {
                 _PyGI_ERROR_PREFIX("argument %zd: ", py_args_pos);
-                goto out;
+                return FALSE;
             }
 
             py_args_pos += 1;
         }
 
-        g_assert(py_args_pos == s.n_py_args);
+        g_assert(py_args_pos == state->n_py_args);
     }
 
-    s.args = g_newa(GArgument *, s.n_args);
-    s.in_args = g_newa(GArgument, s.n_in_args);
-    s.out_args = g_newa(GArgument, s.n_out_args);
-    s.out_values = g_newa(GArgument, s.n_out_args);
-    s.backup_args = g_newa(GArgument, s.n_backup_args);
+    state->args = g_slice_alloc0(sizeof(gpointer) * state->n_args);
+    state->in_args = g_slice_alloc0(sizeof(GArgument) * state->n_in_args);
+    state->out_args = g_slice_alloc0(sizeof(GArgument) * state->n_out_args);
+    state->out_values = g_slice_alloc0(sizeof(GArgument) * state->n_out_args);
+    state->backup_args = g_slice_alloc0(sizeof(GArgument) * state->n_backup_args);
 
     /* Bind args so we can use an unique index. */
     {
         gsize in_args_pos;
         gsize out_args_pos;
 
-        in_args_pos = s.is_method ? 1 : 0;
+        in_args_pos = state->is_method ? 1 : 0;
         out_args_pos = 0;
 
-        for (i = 0; i < s.n_args; i++) {
+        for (i = 0; i < state->n_args; i++) {
             GIDirection direction;
 
-            direction = g_arg_info_get_direction(s.arg_infos[i]);
+            direction = g_arg_info_get_direction(state->arg_infos[i]);
 
             switch (direction) {
                 case GI_DIRECTION_IN:
-                    g_assert(in_args_pos < s.n_in_args);
-                    s.args[i] = &s.in_args[in_args_pos];
+                    g_assert(in_args_pos < state->n_in_args);
+                    state->args[i] = &state->in_args[in_args_pos];
                     in_args_pos += 1;
                     break;
                 case GI_DIRECTION_INOUT:
-                    g_assert(in_args_pos < s.n_in_args);
-                    g_assert(out_args_pos < s.n_out_args);
-                    s.in_args[in_args_pos].v_pointer = &s.out_values[out_args_pos];
+                    g_assert(in_args_pos < state->n_in_args);
+                    g_assert(out_args_pos < state->n_out_args);
+                    state->in_args[in_args_pos].v_pointer = &state->out_values[out_args_pos];
                     in_args_pos += 1;
                 case GI_DIRECTION_OUT:
-                    g_assert(out_args_pos < s.n_out_args);
-                    s.out_args[out_args_pos].v_pointer = &s.out_values[out_args_pos];
-                    s.out_values[out_args_pos].v_pointer = NULL;
-                    s.args[i] = &s.out_values[out_args_pos];
+                    g_assert(out_args_pos < state->n_out_args);
+                    state->out_args[out_args_pos].v_pointer = &state->out_values[out_args_pos];
+                    state->out_values[out_args_pos].v_pointer = NULL;
+                    state->args[i] = &state->out_values[out_args_pos];
                     out_args_pos += 1;
             }
         }
 
-        g_assert(in_args_pos == s.n_in_args);
-        g_assert(out_args_pos == s.n_out_args);
+        g_assert(in_args_pos == state->n_in_args);
+        g_assert(out_args_pos == state->n_out_args);
     }
 
     /* Convert the input arguments. */
@@ -787,19 +793,19 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
         py_args_pos = 0;
         backup_args_pos = 0;
 
-        if (s.is_constructor) {
+        if (state->is_constructor) {
             /* Skip the first argument. */
             py_args_pos += 1;
-        } else if (s.is_method) {
+        } else if (state->is_method) {
             /* Get the instance. */
             GIBaseInfo *container_info;
             GIInfoType container_info_type;
             PyObject *py_arg;
 
-            container_info = g_base_info_get_container(self->info);
+            container_info = g_base_info_get_container(function_info);
             container_info_type = g_base_info_get_type(container_info);
 
-            g_assert(py_args_pos < s.n_py_args);
+            g_assert(py_args_pos < state->n_py_args);
             py_arg = PyTuple_GET_ITEM(py_args, py_args_pos);
 
             switch(container_info_type) {
@@ -811,22 +817,22 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                     type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)container_info);
 
                     if (g_type_is_a(type, G_TYPE_BOXED)) {
-                        g_assert(s.n_in_args > 0);
-                        s.in_args[0].v_pointer = pyg_boxed_get(py_arg, void);
+                        g_assert(state->n_in_args > 0);
+                        state->in_args[0].v_pointer = pyg_boxed_get(py_arg, void);
                     } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
-                        g_assert(s.n_in_args > 0);
-                        s.in_args[0].v_pointer = pyg_pointer_get(py_arg, void);
+                        g_assert(state->n_in_args > 0);
+                        state->in_args[0].v_pointer = pyg_pointer_get(py_arg, void);
                     } else {
                         PyErr_Format(PyExc_TypeError, "unable to convert an instance of '%s'", g_type_name(type));
-                        goto out;
+                        return FALSE;
                     }
 
                     break;
                 }
                 case GI_INFO_TYPE_OBJECT:
                 case GI_INFO_TYPE_INTERFACE:
-                    g_assert(s.n_in_args > 0);
-                    s.in_args[0].v_pointer = pygobject_get(py_arg);
+                    g_assert(state->n_in_args > 0);
+                    state->in_args[0].v_pointer = pygobject_get(py_arg);
                     break;
                 default:
                     /* Other types don't have methods. */
@@ -836,34 +842,34 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
             py_args_pos += 1;
         }
 
-        for (i = 0; i < s.n_args; i++) {
+        for (i = 0; i < state->n_args; i++) {
             GIDirection direction;
 
-            if (i == s.callback_index) {
-                s.args[i]->v_pointer = s.closure->closure;
+            if (i == state->callback_index) {
+                state->args[i]->v_pointer = state->closure->closure;
                 py_args_pos++;
                 continue;
-            } else if (i == s.user_data_index) {
-                s.args[i]->v_pointer = s.closure;
+            } else if (i == state->user_data_index) {
+                state->args[i]->v_pointer = state->closure;
                 py_args_pos++;
                 continue;
-            } else if (i == s.destroy_notify_index) {
-                s.args[i]->v_pointer = _pygi_destroy_notify_create();
+            } else if (i == state->destroy_notify_index) {
+                state->args[i]->v_pointer = _pygi_destroy_notify_create();
                 continue;
             }
             
-            if (s.args_is_auxiliary[i]) {
+            if (state->args_is_auxiliary[i]) {
                 continue;
             }
 
-            direction = g_arg_info_get_direction(s.arg_infos[i]);
+            direction = g_arg_info_get_direction(state->arg_infos[i]);
 
             if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
                 PyObject *py_arg;
                 GITypeTag arg_type_tag;
                 GITransfer transfer;
 
-                arg_type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+                arg_type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
 
                 if (arg_type_tag == GI_TYPE_TAG_ERROR) {
                     GError **error;
@@ -871,26 +877,26 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                     error = g_slice_new(GError *);
                     *error = NULL;
 
-                    s.args[i]->v_pointer = error;
+                    state->args[i]->v_pointer = error;
                     continue;
                 }
 
-                transfer = g_arg_info_get_ownership_transfer(s.arg_infos[i]);
+                transfer = g_arg_info_get_ownership_transfer(state->arg_infos[i]);
 
-                g_assert(py_args_pos < s.n_py_args);
+                g_assert(py_args_pos < state->n_py_args);
                 py_arg = PyTuple_GET_ITEM(py_args, py_args_pos);
 
-                *s.args[i] = _pygi_argument_from_object(py_arg, s.arg_type_infos[i], transfer);
+                *state->args[i] = _pygi_argument_from_object(py_arg, state->arg_type_infos[i], transfer);
 
                 if (PyErr_Occurred()) {
                     /* TODO: release previous input arguments. */
-                    goto out;
+                    return FALSE;
                 }
 
                 if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) {
                     /* We need to keep a copy of the argument to be able to release it later. */
-                    g_assert(backup_args_pos < s.n_backup_args);
-                    s.backup_args[backup_args_pos] = *s.args[i];
+                    g_assert(backup_args_pos < state->n_backup_args);
+                    state->backup_args[backup_args_pos] = *state->args[i];
                     backup_args_pos += 1;
                 } else if (transfer == GI_TRANSFER_CONTAINER) {
                     /* We need to keep a copy of the items to be able to release them later. */
@@ -901,25 +907,25 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                             gsize item_size;
                             GArray *new_array;
 
-                            array = s.args[i]->v_pointer;
+                            array = state->args[i]->v_pointer;
 
                             item_size = g_array_get_element_size(array);
 
                             new_array = g_array_sized_new(FALSE, FALSE, item_size, array->len);
                             g_array_append_vals(new_array, array->data, array->len);
 
-                            g_assert(backup_args_pos < s.n_backup_args);
-                            s.backup_args[backup_args_pos].v_pointer = new_array;
+                            g_assert(backup_args_pos < state->n_backup_args);
+                            state->backup_args[backup_args_pos].v_pointer = new_array;
 
                             break;
                         }
                         case GI_TYPE_TAG_GLIST:
-                            g_assert(backup_args_pos < s.n_backup_args);
-                            s.backup_args[backup_args_pos].v_pointer = g_list_copy(s.args[i]->v_pointer);
+                            g_assert(backup_args_pos < state->n_backup_args);
+                            state->backup_args[backup_args_pos].v_pointer = g_list_copy(state->args[i]->v_pointer);
                             break;
                         case GI_TYPE_TAG_GSLIST:
-                            g_assert(backup_args_pos < s.n_backup_args);
-                            s.backup_args[backup_args_pos].v_pointer = g_slist_copy(s.args[i]->v_pointer);
+                            g_assert(backup_args_pos < state->n_backup_args);
+                            state->backup_args[backup_args_pos].v_pointer = g_slist_copy(state->args[i]->v_pointer);
                             break;
                         case GI_TYPE_TAG_GHASH:
                         {
@@ -927,13 +933,13 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                             GList *keys;
                             GList *values;
 
-                            hash_table = s.args[i]->v_pointer;
+                            hash_table = state->args[i]->v_pointer;
 
                             keys = g_hash_table_get_keys(hash_table);
                             values = g_hash_table_get_values(hash_table);
 
-                            g_assert(backup_args_pos < s.n_backup_args);
-                            s.backup_args[backup_args_pos].v_pointer = g_list_concat(keys, values);
+                            g_assert(backup_args_pos < state->n_backup_args);
+                            state->backup_args[backup_args_pos].v_pointer = g_list_concat(keys, values);
 
                             break;
                         }
@@ -948,19 +954,19 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                     GArray *array;
                     gssize length_arg_pos;
 
-                    array = s.args[i]->v_pointer;
+                    array = state->args[i]->v_pointer;
 
-                    length_arg_pos = g_type_info_get_array_length(s.arg_type_infos[i]);
-                    if (s.is_method)
+                    length_arg_pos = g_type_info_get_array_length(state->arg_type_infos[i]);
+                    if (state->is_method)
                         length_arg_pos--; // length_arg_pos refers to C args
                     if (length_arg_pos >= 0) {
                         /* Set the auxiliary argument holding the length. */
-                        s.args[length_arg_pos]->v_size = array->len;
+                        state->args[length_arg_pos]->v_size = array->len;
                     }
 
                     /* Get rid of the GArray. */
                     if (array != NULL) {
-                        s.args[i]->v_pointer = array->data;
+                        state->args[i]->v_pointer = array->data;
 
                         if (direction != GI_DIRECTION_INOUT || transfer != GI_TRANSFER_NOTHING) {
                             /* The array hasn't been referenced anywhere, so free it to avoid losing memory. */
@@ -973,35 +979,39 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
             }
         }
 
-        g_assert(py_args_pos == s.n_py_args);
-        g_assert(backup_args_pos == s.n_backup_args);
+        g_assert(py_args_pos == state->n_py_args);
+        g_assert(backup_args_pos == state->n_backup_args);
     }
 
-    /* Invoke the callable. */
-    {
-        GError *error;
-        gint retval;
+    return TRUE;
+}
 
-        error = NULL;
+static gboolean
+_invoke_function (struct invocation_state *state,
+                  GIFunctionInfo *function_info, PyObject *py_args)
+{
+    GError *error;
+    gint retval;
 
-        retval = g_function_info_invoke((GIFunctionInfo *)self->info,
-                s.in_args, s.n_in_args, s.out_args, s.n_out_args, &s.return_arg, &error);
-        if (!retval) {
-            g_assert(error != NULL);
-            /* TODO: raise the right error, out of the error domain. */
-            PyErr_SetString(PyExc_RuntimeError, error->message);
-            g_error_free(error);
+    error = NULL;
 
-            /* TODO: release input arguments. */
+    retval = g_function_info_invoke((GIFunctionInfo *)function_info,
+            state->in_args, state->n_in_args, state->out_args, state->n_out_args, &state->return_arg, &error);
+    if (!retval) {
+        g_assert(error != NULL);
+        /* TODO: raise the right error, out of the error domain. */
+        PyErr_SetString(PyExc_RuntimeError, error->message);
+        g_error_free(error);
 
-            goto out;
-        }
+        /* TODO: release input arguments. */
+
+        return FALSE;
     }
 
-    if (s.error_arg_pos >= 0) {
+    if (state->error_arg_pos >= 0) {
         GError **error;
 
-        error = s.args[s.error_arg_pos]->v_pointer;
+        error = state->args[state->error_arg_pos]->v_pointer;
 
         if (*error != NULL) {
             /* TODO: raise the right error, out of the error domain, if applicable. */
@@ -1010,33 +1020,42 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
 
             /* TODO: release input arguments. */
 
-            goto out;
+            return FALSE;
         }
     }
 
+    return TRUE;
+}
+
+static gboolean
+_process_invocation_state (struct invocation_state *state,
+                           GIFunctionInfo *function_info, PyObject *py_args)
+{
+    gsize i;
+
     /* Convert the return value. */
-    if (s.is_constructor) {
+    if (state->is_constructor) {
         PyTypeObject *py_type;
         GIBaseInfo *info;
         GIInfoType info_type;
         GITransfer transfer;
 
-        g_assert(s.n_py_args > 0);
+        g_assert(state->n_py_args > 0);
         py_type = (PyTypeObject *)PyTuple_GET_ITEM(py_args, 0);
 
-        info = g_type_info_get_interface(s.return_type_info);
+        info = g_type_info_get_interface(state->return_type_info);
         g_assert(info != NULL);
 
         info_type = g_base_info_get_type(info);
 
-        transfer = g_callable_info_get_caller_owns((GICallableInfo *)self->info);
+        transfer = g_callable_info_get_caller_owns((GICallableInfo *)function_info);
 
         switch (info_type) {
             case GI_INFO_TYPE_UNION:
                 /* TODO */
                 PyErr_SetString(PyExc_NotImplementedError, "creating unions is not supported yet");
                 g_base_info_unref(info);
-                goto out;
+                return FALSE;
             case GI_INFO_TYPE_STRUCT:
             {
                 GType type;
@@ -1044,36 +1063,36 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                 type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info);
 
                 if (g_type_is_a(type, G_TYPE_BOXED)) {
-                    if (s.return_arg.v_pointer == NULL) {
+                    if (state->return_arg.v_pointer == NULL) {
                         PyErr_SetString(PyExc_TypeError, "constructor returned NULL");
                         break;
                     }
                     g_warn_if_fail(transfer == GI_TRANSFER_EVERYTHING);
-                    s.return_value = _pygi_boxed_new(py_type, s.return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+                    state->return_value = _pygi_boxed_new(py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
                 } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
-                    if (s.return_arg.v_pointer == NULL) {
+                    if (state->return_arg.v_pointer == NULL) {
                         PyErr_SetString(PyExc_TypeError, "constructor returned NULL");
                         break;
                     }
                     g_warn_if_fail(transfer == GI_TRANSFER_NOTHING);
-                    s.return_value = _pygi_struct_new(py_type, s.return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+                    state->return_value = _pygi_struct_new(py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
                 } else {
                     PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", py_type->tp_name);
                     g_base_info_unref(info);
-                    goto out;
+                    return FALSE;
                 }
 
                 break;
             }
             case GI_INFO_TYPE_OBJECT:
-                if (s.return_arg.v_pointer == NULL) {
+                if (state->return_arg.v_pointer == NULL) {
                     PyErr_SetString(PyExc_TypeError, "constructor returned NULL");
                     break;
                 }
-                s.return_value = pygobject_new(s.return_arg.v_pointer);
+                state->return_value = pygobject_new(state->return_arg.v_pointer);
                 if (transfer == GI_TRANSFER_EVERYTHING) {
                     /* The new wrapper increased the reference count, so decrease it. */
-                    g_object_unref (s.return_arg.v_pointer);
+                    g_object_unref (state->return_arg.v_pointer);
                 }
                 break;
             default:
@@ -1083,32 +1102,32 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
 
         g_base_info_unref(info);
 
-        if (s.return_value == NULL) {
+        if (state->return_value == NULL) {
             /* TODO: release arguments. */
-            goto out;
+            return FALSE;
         }
     } else {
         GITransfer transfer;
 
-        if (s.return_type_tag == GI_TYPE_TAG_ARRAY) {
+        if (state->return_type_tag == GI_TYPE_TAG_ARRAY) {
             /* Create a #GArray. */
-            s.return_arg.v_pointer = _pygi_argument_to_array(&s.return_arg, s.args, s.return_type_info, s.is_method);
+            state->return_arg.v_pointer = _pygi_argument_to_array(&state->return_arg, state->args, state->return_type_info, state->is_method);
         }
 
-        transfer = g_callable_info_get_caller_owns((GICallableInfo *)self->info);
+        transfer = g_callable_info_get_caller_owns((GICallableInfo *)function_info);
 
-        s.return_value = _pygi_argument_to_object(&s.return_arg, s.return_type_info, transfer);
-        if (s.return_value == NULL) {
+        state->return_value = _pygi_argument_to_object(&state->return_arg, state->return_type_info, transfer);
+        if (state->return_value == NULL) {
             /* TODO: release argument. */
-            goto out;
+            return FALSE;
         }
 
-        _pygi_argument_release(&s.return_arg, s.return_type_info, transfer, GI_DIRECTION_OUT);
+        _pygi_argument_release(&state->return_arg, state->return_type_info, transfer, GI_DIRECTION_OUT);
 
-        if (s.return_type_tag == GI_TYPE_TAG_ARRAY
+        if (state->return_type_tag == GI_TYPE_TAG_ARRAY
                 && transfer == GI_TRANSFER_NOTHING) {
             /* We created a #GArray, so free it. */
-            s.return_arg.v_pointer = g_array_free(s.return_arg.v_pointer, FALSE);
+            state->return_arg.v_pointer = g_array_free(state->return_arg.v_pointer, FALSE);
         }
     }
 
@@ -1120,68 +1139,68 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
         backup_args_pos = 0;
         return_values_pos = 0;
 
-        if (s.n_return_values > 1) {
+        if (state->n_return_values > 1) {
             /* Return a tuple. */
             PyObject *return_values;
 
-            return_values = PyTuple_New(s.n_return_values);
+            return_values = PyTuple_New(state->n_return_values);
             if (return_values == NULL) {
                 /* TODO: release arguments. */
-                goto out;
+                return FALSE;
             }
 
-            if (s.return_type_tag == GI_TYPE_TAG_VOID) {
+            if (state->return_type_tag == GI_TYPE_TAG_VOID) {
                 /* The current return value is None. */
-                Py_DECREF(s.return_value);
+                Py_DECREF(state->return_value);
             } else {
                 /* Put the return value first. */
-                g_assert(s.return_value != NULL);
-                PyTuple_SET_ITEM(return_values, return_values_pos, s.return_value);
+                g_assert(state->return_value != NULL);
+                PyTuple_SET_ITEM(return_values, return_values_pos, state->return_value);
                 return_values_pos += 1;
             }
 
-            s.return_value = return_values;
+            state->return_value = return_values;
         }
 
-        for (i = 0; i < s.n_args; i++) {
+        for (i = 0; i < state->n_args; i++) {
             GIDirection direction;
             GITypeTag type_tag;
             GITransfer transfer;
 
-            if (s.args_is_auxiliary[i]) {
+            if (state->args_is_auxiliary[i]) {
                 /* Auxiliary arguments are handled at the same time as their relatives. */
                 continue;
             }
 
-            direction = g_arg_info_get_direction(s.arg_infos[i]);
-            transfer = g_arg_info_get_ownership_transfer(s.arg_infos[i]);
+            direction = g_arg_info_get_direction(state->arg_infos[i]);
+            transfer = g_arg_info_get_ownership_transfer(state->arg_infos[i]);
 
-            type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+            type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
 
             if (type_tag == GI_TYPE_TAG_ARRAY
                     && (direction != GI_DIRECTION_IN || transfer == GI_TRANSFER_NOTHING)) {
                 /* Create a #GArray. */
-                s.args[i]->v_pointer = _pygi_argument_to_array(s.args[i], s.args, s.arg_type_infos[i], s.is_method);
+                state->args[i]->v_pointer = _pygi_argument_to_array(state->args[i], state->args, state->arg_type_infos[i], state->is_method);
             }
 
             if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT) {
                 /* Convert the argument. */
                 PyObject *obj;
 
-                obj = _pygi_argument_to_object(s.args[i], s.arg_type_infos[i], transfer);
+                obj = _pygi_argument_to_object(state->args[i], state->arg_type_infos[i], transfer);
                 if (obj == NULL) {
                     /* TODO: release arguments. */
-                    goto out;
+                    return FALSE;
                 }
 
-                g_assert(return_values_pos < s.n_return_values);
+                g_assert(return_values_pos < state->n_return_values);
 
-                if (s.n_return_values > 1) {
-                    PyTuple_SET_ITEM(s.return_value, return_values_pos, obj);
+                if (state->n_return_values > 1) {
+                    PyTuple_SET_ITEM(state->return_value, return_values_pos, obj);
                 } else {
                     /* The current return value is None. */
-                    Py_DECREF(s.return_value);
-                    s.return_value = obj;
+                    Py_DECREF(state->return_value);
+                    state->return_value = obj;
                 }
 
                 return_values_pos += 1;
@@ -1196,8 +1215,8 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                     case GI_TYPE_TAG_ARRAY:
                     case GI_TYPE_TAG_GLIST:
                     case GI_TYPE_TAG_GSLIST:
-                        g_assert(backup_args_pos < s.n_backup_args);
-                        _pygi_argument_release(&s.backup_args[backup_args_pos], s.arg_type_infos[i],
+                        g_assert(backup_args_pos < state->n_backup_args);
+                        _pygi_argument_release(&state->backup_args[backup_args_pos], state->arg_type_infos[i],
                             transfer, GI_DIRECTION_IN);
                         break;
                     case GI_TYPE_TAG_GHASH:
@@ -1208,11 +1227,11 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                         gsize length;
                         gsize j;
 
-                        key_type_info = g_type_info_get_param_type(s.arg_type_infos[i], 0);
-                        value_type_info = g_type_info_get_param_type(s.arg_type_infos[i], 1);
+                        key_type_info = g_type_info_get_param_type(state->arg_type_infos[i], 0);
+                        value_type_info = g_type_info_get_param_type(state->arg_type_infos[i], 1);
 
-                        g_assert(backup_args_pos < s.n_backup_args);
-                        item = s.backup_args[backup_args_pos].v_pointer;
+                        g_assert(backup_args_pos < state->n_backup_args);
+                        item = state->backup_args[backup_args_pos].v_pointer;
 
                         length = g_list_length(item) / 2;
 
@@ -1226,7 +1245,7 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
                                 GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
                         }
 
-                        g_list_free(s.backup_args[backup_args_pos].v_pointer);
+                        g_list_free(state->backup_args[backup_args_pos].v_pointer);
 
                         break;
                     }
@@ -1236,54 +1255,119 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
 
                 if (direction == GI_DIRECTION_INOUT) {
                     /* Release the output argument. */
-                    _pygi_argument_release(s.args[i], s.arg_type_infos[i], GI_TRANSFER_CONTAINER,
+                    _pygi_argument_release(state->args[i], state->arg_type_infos[i], GI_TRANSFER_CONTAINER,
                         GI_DIRECTION_OUT);
                 }
 
                 backup_args_pos += 1;
             } else if (direction == GI_DIRECTION_INOUT) {
                 if (transfer == GI_TRANSFER_NOTHING) {
-                    g_assert(backup_args_pos < s.n_backup_args);
-                    _pygi_argument_release(&s.backup_args[backup_args_pos], s.arg_type_infos[i],
+                    g_assert(backup_args_pos < state->n_backup_args);
+                    _pygi_argument_release(&state->backup_args[backup_args_pos], state->arg_type_infos[i],
                         GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
                     backup_args_pos += 1;
                 }
 
-                _pygi_argument_release(s.args[i], s.arg_type_infos[i], transfer,
+                _pygi_argument_release(state->args[i], state->arg_type_infos[i], transfer,
                     GI_DIRECTION_OUT);
             } else {
-                _pygi_argument_release(s.args[i], s.arg_type_infos[i], transfer, direction);
+                _pygi_argument_release(state->args[i], state->arg_type_infos[i], transfer, direction);
             }
 
             if (type_tag == GI_TYPE_TAG_ARRAY
                     && (direction != GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) {
                 /* We created a #GArray and it has not been released above, so free it. */
-                s.args[i]->v_pointer = g_array_free(s.args[i]->v_pointer, FALSE);
+                state->args[i]->v_pointer = g_array_free(state->args[i]->v_pointer, FALSE);
             }
         }
 
-        g_assert(s.n_return_values <= 1 || return_values_pos == s.n_return_values);
-        g_assert(backup_args_pos == s.n_backup_args);
+        g_assert(state->n_return_values <= 1 || return_values_pos == state->n_return_values);
+        g_assert(backup_args_pos == state->n_backup_args);
     }
 
-out:
-    g_base_info_unref((GIBaseInfo *)s.return_type_info);
+    return TRUE;
+}
+
+static void
+_free_invocation_state (struct invocation_state *state)
+{
+    gsize i;
+
+    if (state->return_type_info != NULL) {
+        g_base_info_unref((GIBaseInfo *)state->return_type_info);
+    }
+
+    if (state->closure != NULL) {
+        if (state->closure->scope == GI_SCOPE_TYPE_CALL) 
+            _pygi_invoke_closure_free(state->closure);
+    }
+
+    for (i = 0; i < state->n_args; i++) {
+        g_base_info_unref((GIBaseInfo *)state->arg_type_infos[i]);
+        g_base_info_unref((GIBaseInfo *)state->arg_infos[i]);
+    }
+
+    if (state->arg_infos != NULL) {
+        g_slice_free1(sizeof(gpointer) * state->n_args, state->arg_infos);
+    }
+
+    if (state->arg_type_infos != NULL) {
+        g_slice_free1(sizeof(gpointer) * state->n_args, state->arg_type_infos);
+    }
+
+    if (state->args != NULL) {
+        g_slice_free1(sizeof(gpointer) * state->n_args, state->args);
+    }
+
+    if (state->args_is_auxiliary != NULL) {
+        g_slice_free1(sizeof(gboolean) * state->n_args, state->args_is_auxiliary);
+    }
 
-    if (s.closure != NULL) {
-        if (s.closure->scope == GI_SCOPE_TYPE_CALL) 
-            _pygi_invoke_closure_free(s.closure);
+    if (state->in_args != NULL) {
+        g_slice_free1(sizeof(GArgument) * state->n_in_args, state->in_args);
     }
 
-    for (i = 0; i < s.n_args; i++) {
-        g_base_info_unref((GIBaseInfo *)s.arg_type_infos[i]);
-        g_base_info_unref((GIBaseInfo *)s.arg_infos[i]);
+    if (state->out_args != NULL) {
+        g_slice_free1(sizeof(GArgument) * state->n_out_args, state->out_args);
+    }
+
+    if (state->out_values != NULL) {
+        g_slice_free1(sizeof(GArgument) * state->n_out_args, state->out_values);
+    }
+
+    if (state->backup_args != NULL) {
+        g_slice_free1(sizeof(GArgument) * state->n_backup_args, state->backup_args);
     }
 
     if (PyErr_Occurred()) {
-        Py_CLEAR(s.return_value);
+        Py_CLEAR(state->return_value);
+    }
+}
+
+
+static PyObject *
+_wrap_g_function_info_invoke (PyGIBaseInfo *self, PyObject *py_args)
+{
+    struct invocation_state state;
+
+    _initialize_invocation_state (&state, self->info, py_args);
+
+    if (!_prepare_invocation_state (&state, self->info, py_args)) {
+        _free_invocation_state (&state);
+        return NULL;
+    }
+
+    if (!_invoke_function (&state, self->info, py_args)) {
+        _free_invocation_state (&state);
+        return NULL;
+    }
+
+    if (!_process_invocation_state (&state, self->info, py_args)) {
+        _free_invocation_state (&state);
+        return NULL;
     }
 
-    return s.return_value;
+    return state.return_value;
 }
 
 static PyMethodDef _PyGIFunctionInfo_methods[] = {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]