[perl-Glib-Object-Introspection/ppc64-fixes: 1/6] Factor our the common parts of the invocation infos for C and Perl code



commit 3bbdc310ec79c6a73281d17f17627fec064a614e
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date:   Fri Sep 5 18:02:42 2014 +0200

    Factor our the common parts of the invocation infos for C and Perl code

 GObjectIntrospection.xs  |   79 ++++++++++++++++-------
 MANIFEST                 |    1 +
 gperl-i11n-invoke-c.c    |  157 +++++++++++++++-------------------------------
 gperl-i11n-invoke-perl.c |   66 +++++++-------------
 gperl-i11n-invoke.c      |   85 +++++++++++++++++++++++++
 5 files changed, 215 insertions(+), 173 deletions(-)
---
diff --git a/GObjectIntrospection.xs b/GObjectIntrospection.xs
index 0885db0..21327c7 100644
--- a/GObjectIntrospection.xs
+++ b/GObjectIntrospection.xs
@@ -82,52 +82,76 @@ typedef struct {
        gint length_pos;
 } GPerlI11nArrayInfo;
 
-/* This stores information that the different marshallers might need to
- * communicate to each other.  This struct is used for invoking C and Perl
- * code. */
+/* The next three structs store information that the different marshallers
+ * might need to communicate to each other.  This struct is the basis used for
+ * invoking C and Perl code. */
 typedef struct {
        GICallableInfo *interface;
-       const gchar *target_package;
-       const gchar *target_namespace;
-       const gchar *target_function;
 
        gboolean is_function;
        gboolean is_vfunc;
        gboolean is_callback;
        gboolean is_signal;
 
+       /* The number of args described by the typelib. */
        guint n_args;
-       guint n_invoke_args;
-       guint n_expected_args;
-       guint n_nullable_args;
-       guint n_given_args;
+
+       /* The current position under investigation in the list of typelib
+        * args. */
+       guint current_pos;
+
+       /* An array of places for storing out out/in-out or automatic args. */
+       GIArgument * aux_args;
+
+       gboolean has_return_value;
+       ffi_type * return_type_ffi;
+       GITypeInfo * return_type_info;
+       GITransfer return_type_transfer;
+
+       GSList * callback_infos;
+       GSList * array_infos;
+
+       GSList * free_after_call;
+} GPerlI11nInvocationInfo;
+
+/* This struct is used when invoking C code. */
+typedef struct {
+       GPerlI11nInvocationInfo base;
+
+       const gchar *target_package;
+       const gchar *target_namespace;
+       const gchar *target_function;
+
        gboolean is_constructor;
        gboolean is_method;
        gboolean throws;
 
+       /* The number of args that need to be given to the C function. */
+       guint n_invoke_args;
+       /* The number of args for which no value is required. */
+       guint n_nullable_args;
+       /* The number of necessary args, i.e. those that are not automatic or
+        * nullable. */
+       guint n_expected_args;
+       /* The number of args given by the caller. */
+       guint n_given_args;
+
        gpointer * args;
        ffi_type ** arg_types;
        GIArgument * in_args;
        GIArgument * out_args;
        GITypeInfo ** out_arg_infos;
-       GIArgument * aux_args;
        gboolean * is_automatic_arg;
 
-       gboolean has_return_value;
-       ffi_type * return_type_ffi;
-       GITypeInfo * return_type_info;
-       GITransfer return_type_transfer;
-
-       guint current_pos;
        guint method_offset;
        guint stack_offset;
        gint dynamic_stack_offset;
+} GPerlI11nCInvocationInfo;
 
-       GSList * callback_infos;
-       GSList * free_after_call;
-
-       GSList * array_infos;
-} GPerlI11nInvocationInfo;
+/* This struct is used when invoking Perl code. */
+typedef struct {
+       GPerlI11nInvocationInfo base;
+} GPerlI11nPerlInvocationInfo;
 
 /* callbacks */
 static GPerlI11nPerlCallbackInfo * create_perl_callback_closure_for_named_sub (GIBaseInfo *cb_info, gchar 
*sub_name);
@@ -140,6 +164,14 @@ static void attach_c_callback_data (GPerlI11nCCallbackInfo *info, gpointer data)
 static void release_c_callback (gpointer data);
 
 /* invocation */
+static void prepare_invocation_info (GPerlI11nInvocationInfo *iinfo,
+                                     GICallableInfo *info);
+static void clear_invocation_info (GPerlI11nInvocationInfo *iinfo);
+
+static void free_after_call (GPerlI11nInvocationInfo *iinfo,
+                             GFunc func, gpointer data);
+static void invoke_free_after_call_handlers (GPerlI11nInvocationInfo *iinfo);
+
 #if GI_CHECK_VERSION (1, 33, 10)
 static void invoke_perl_signal_handler (ffi_cif* cif,
                                         gpointer resp,
@@ -159,8 +191,6 @@ static void invoke_c_code (GICallableInfo *info,
                            const gchar *package,
                            const gchar *namespace,
                            const gchar *function);
-static void free_after_call (GPerlI11nInvocationInfo *iinfo,
-                             GFunc func, gpointer data);
 
 /* info finders */
 static GIFunctionInfo * get_function_info (GIRepository *repository,
@@ -283,6 +313,7 @@ static void call_carp_carp (const char *msg);
 #include "gperl-i11n-field.c"
 #include "gperl-i11n-gvalue.c"
 #include "gperl-i11n-info.c"
+#include "gperl-i11n-invoke.c"
 #include "gperl-i11n-invoke-c.c"
 #include "gperl-i11n-invoke-perl.c"
 #include "gperl-i11n-marshal-arg.c"
diff --git a/MANIFEST b/MANIFEST
index a21311f..aa64715 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -5,6 +5,7 @@ gperl-i11n-enums.c
 gperl-i11n-field.c
 gperl-i11n-gvalue.c
 gperl-i11n-info.c
+gperl-i11n-invoke.c
 gperl-i11n-invoke-c.c
 gperl-i11n-invoke-perl.c
 gperl-i11n-marshal-arg.c
diff --git a/gperl-i11n-invoke-c.c b/gperl-i11n-invoke-c.c
index 1497836..075fe95 100644
--- a/gperl-i11n-invoke-c.c
+++ b/gperl-i11n-invoke-c.c
@@ -1,19 +1,18 @@
 /* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
 
-static void _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
+static void _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
                                         GICallableInfo *info,
                                         IV items,
                                         UV internal_stack_offset,
                                         const gchar *package,
                                         const gchar *namespace,
                                         const gchar *function);
-static void _clear_c_invocation_info (GPerlI11nInvocationInfo *iinfo);
-static void _check_n_args (GPerlI11nInvocationInfo *iinfo);
+static void _clear_c_invocation_info (GPerlI11nCInvocationInfo *iinfo);
+static void _check_n_args (GPerlI11nCInvocationInfo *iinfo);
 static void _handle_automatic_arg (guint pos,
                                    GIArgument * arg,
-                                   GPerlI11nInvocationInfo * invocation_info);
+                                   GPerlI11nCInvocationInfo * invocation_info);
 static gpointer _allocate_out_mem (GITypeInfo *arg_type);
-static void _invoke_free_after_call_handlers (GPerlI11nInvocationInfo *iinfo);
 
 static void
 invoke_c_code (GICallableInfo *info,
@@ -27,7 +26,7 @@ invoke_c_code (GICallableInfo *info,
        ffi_cif cif;
        gpointer instance = NULL;
        guint i;
-       GPerlI11nInvocationInfo iinfo = {0,};
+       GPerlI11nCInvocationInfo iinfo;
        guint n_return_values;
 #if GI_CHECK_VERSION (1, 32, 0)
        GIFFIReturnValue ffi_return_value;
@@ -54,7 +53,7 @@ invoke_c_code (GICallableInfo *info,
         * --- handle arguments -----------------------------------------------
         */
 
-       for (i = 0 ; i < iinfo.n_args ; i++) {
+       for (i = 0 ; i < iinfo.base.n_args ; i++) {
                GIArgInfo * arg_info;
                GITypeInfo * arg_type;
                GITransfer transfer;
@@ -83,7 +82,7 @@ invoke_c_code (GICallableInfo *info,
                 * g_arg_info_get_closure and g_arg_info_get_destroy.  We used
                 * to add method_offset, but that stopped being correct at some
                 * point. */
-               iinfo.current_pos = i; /* + method_offset; */
+               iinfo.base.current_pos = i; /* + method_offset; */
 
                dwarn ("  arg %d, tag: %d (%s), is_pointer: %d, is_automatic: %d\n",
                       i,
@@ -105,7 +104,7 @@ invoke_c_code (GICallableInfo *info,
                        } else {
                                sv_to_arg (current_sv,
                                           &iinfo.in_args[i], arg_info, arg_type,
-                                          transfer, may_be_null, &iinfo);
+                                          transfer, may_be_null, &iinfo.base);
                        }
                        iinfo.arg_types[ffi_stack_pos] =
                                g_type_info_get_ffi_type (arg_type);
@@ -115,12 +114,12 @@ invoke_c_code (GICallableInfo *info,
 
                    case GI_DIRECTION_OUT:
                        if (g_arg_info_is_caller_allocates (arg_info)) {
-                               iinfo.aux_args[i].v_pointer =
+                               iinfo.base.aux_args[i].v_pointer =
                                        _allocate_out_mem (arg_type);
-                               iinfo.out_args[i].v_pointer = &iinfo.aux_args[i];
-                               iinfo.args[ffi_stack_pos] = &iinfo.aux_args[i];
+                               iinfo.out_args[i].v_pointer = &iinfo.base.aux_args[i];
+                               iinfo.args[ffi_stack_pos] = &iinfo.base.aux_args[i];
                        } else {
-                               iinfo.out_args[i].v_pointer = &iinfo.aux_args[i];
+                               iinfo.out_args[i].v_pointer = &iinfo.base.aux_args[i];
                                iinfo.args[ffi_stack_pos] = &iinfo.out_args[i];
                        }
                        iinfo.out_arg_infos[i] = arg_type;
@@ -133,7 +132,7 @@ invoke_c_code (GICallableInfo *info,
                    case GI_DIRECTION_INOUT:
                        iinfo.in_args[i].v_pointer =
                                iinfo.out_args[i].v_pointer =
-                                       &iinfo.aux_args[i];
+                                       &iinfo.base.aux_args[i];
                        if (iinfo.is_automatic_arg[i]) {
                                iinfo.dynamic_stack_offset--;
                        } else if (is_skipped) {
@@ -144,7 +143,7 @@ invoke_c_code (GICallableInfo *info,
                                 * pointed to is filled from the SV. */
                                sv_to_arg (current_sv,
                                           iinfo.in_args[i].v_pointer, arg_info, arg_type,
-                                          transfer, may_be_null, &iinfo);
+                                          transfer, may_be_null, &iinfo.base);
                        }
                        iinfo.out_arg_infos[i] = arg_type;
                        iinfo.arg_types[ffi_stack_pos] = &ffi_type_pointer;
@@ -156,7 +155,7 @@ invoke_c_code (GICallableInfo *info,
        }
 
        /* do another pass to handle automatic args */
-       for (i = 0 ; i < iinfo.n_args ; i++) {
+       for (i = 0 ; i < iinfo.base.n_args ; i++) {
                GIArgInfo * arg_info;
                if (!iinfo.is_automatic_arg[i])
                        continue;
@@ -166,7 +165,7 @@ invoke_c_code (GICallableInfo *info,
                        _handle_automatic_arg (i, &iinfo.in_args[i], &iinfo);
                        break;
                    case GI_DIRECTION_INOUT:
-                       _handle_automatic_arg (i, &iinfo.aux_args[i], &iinfo);
+                       _handle_automatic_arg (i, &iinfo.base.aux_args[i], &iinfo);
                        break;
                    case GI_DIRECTION_OUT:
                        /* handled later */
@@ -186,7 +185,7 @@ invoke_c_code (GICallableInfo *info,
 
        /* prepare and call the function */
        if (FFI_OK != ffi_prep_cif (&cif, FFI_DEFAULT_ABI, iinfo.n_invoke_args,
-                                   iinfo.return_type_ffi, iinfo.arg_types))
+                                   iinfo.base.return_type_ffi, iinfo.arg_types))
        {
                _clear_c_invocation_info (&iinfo);
                ccroak ("Could not prepare a call interface");
@@ -206,7 +205,7 @@ invoke_c_code (GICallableInfo *info,
        SPAGAIN;
 
        /* free call-scoped data */
-       _invoke_free_after_call_handlers (&iinfo);
+       invoke_free_after_call_handlers (&iinfo.base);
 
        if (local_error) {
                gperl_croak_gerror (NULL, local_error);
@@ -219,7 +218,7 @@ invoke_c_code (GICallableInfo *info,
 #if GI_CHECK_VERSION (1, 32, 0)
        /* libffi has special semantics for return value storage; see `man
         * ffi_call`.  We use gobject-introspection's extraction helper. */
-       gi_type_info_extract_ffi_return_value (iinfo.return_type_info,
+       gi_type_info_extract_ffi_return_value (iinfo.base.return_type_info,
                                               &ffi_return_value,
                                               &return_value);
 #endif
@@ -227,7 +226,7 @@ invoke_c_code (GICallableInfo *info,
        n_return_values = 0;
 
        /* place return value and output args on the stack */
-       if (iinfo.has_return_value
+       if (iinfo.base.has_return_value
 #if GI_CHECK_VERSION (1, 29, 0)
            && !g_callable_info_skip_return ((GICallableInfo *) info)
 #endif
@@ -235,9 +234,9 @@ invoke_c_code (GICallableInfo *info,
        {
                SV *value;
                value = SAVED_STACK_SV (arg_to_sv (&return_value,
-                                                  iinfo.return_type_info,
-                                                  iinfo.return_type_transfer,
-                                                  &iinfo));
+                                                  iinfo.base.return_type_info,
+                                                  iinfo.base.return_type_transfer,
+                                                  &iinfo.base));
                if (value) {
                        XPUSHs (sv_2mortal (value));
                        n_return_values++;
@@ -245,7 +244,7 @@ invoke_c_code (GICallableInfo *info,
        }
 
        /* out args */
-       for (i = 0 ; i < iinfo.n_args ; i++) {
+       for (i = 0 ; i < iinfo.base.n_args ; i++) {
                GIArgInfo * arg_info;
                if (iinfo.is_automatic_arg[i])
                        continue;
@@ -269,7 +268,7 @@ invoke_c_code (GICallableInfo *info,
                        sv = SAVED_STACK_SV (arg_to_sv (iinfo.out_args[i].v_pointer,
                                                        iinfo.out_arg_infos[i],
                                                        transfer,
-                                                       &iinfo));
+                                                       &iinfo.base));
                        if (sv) {
                                XPUSHs (sv_2mortal (sv));
                                n_return_values++;
@@ -294,7 +293,7 @@ invoke_c_code (GICallableInfo *info,
 /* ------------------------------------------------------------------------- */
 
 static void
-_prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
+_prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
                             GICallableInfo *info,
                             IV items,
                             UV internal_stack_offset,
@@ -304,52 +303,49 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
 {
        guint i;
 
+       prepare_invocation_info ((GPerlI11nInvocationInfo *) iinfo, info);
+
        dwarn ("C invoke: %s::%s::%s => %s\n"
               "  n_args: %d\n",
               package, namespace, function,
               g_base_info_get_name (info),
               g_callable_info_get_n_args (info));
 
-       iinfo->interface = info;
        iinfo->target_package = package;
        iinfo->target_namespace = namespace;
        iinfo->target_function = function;
 
-       iinfo->is_function = GI_IS_FUNCTION_INFO (info);
-       iinfo->is_vfunc = GI_IS_VFUNC_INFO (info);
-       iinfo->is_callback = (g_base_info_get_type (info) == GI_INFO_TYPE_CALLBACK);
-       dwarn ("  is_function = %d, is_vfunc = %d, is_callback = %d\n",
-              iinfo->is_function, iinfo->is_vfunc, iinfo->is_callback);
-
        iinfo->stack_offset = internal_stack_offset;
 
        iinfo->is_constructor = FALSE;
-       if (iinfo->is_function) {
+       if (iinfo->base.is_function) {
                iinfo->is_constructor =
                        g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR;
        }
        if (iinfo->is_constructor) {
+               /* If we call a constructor, we skip the initial package name
+                * resulting from the "Package->new" syntax. */
                iinfo->stack_offset++;
        }
 
        iinfo->n_given_args = items - iinfo->stack_offset;
 
-       iinfo->n_invoke_args = iinfo->n_args =
-               g_callable_info_get_n_args ((GICallableInfo *) info);
+       iinfo->n_invoke_args = iinfo->base.n_args;
 
        /* FIXME: can a vfunc not throw? */
        iinfo->throws = FALSE;
-       if (iinfo->is_function) {
+       if (iinfo->base.is_function) {
                iinfo->throws =
                        g_function_info_get_flags (info) & GI_FUNCTION_THROWS;
        }
        if (iinfo->throws) {
+               /* Add one for the implicit GError arg. */
                iinfo->n_invoke_args++;
        }
 
-       if (iinfo->is_vfunc) {
+       if (iinfo->base.is_vfunc) {
                iinfo->is_method = TRUE;
-       } else if (iinfo->is_callback) {
+       } else if (iinfo->base.is_callback) {
                iinfo->is_method = FALSE;
        } else {
                iinfo->is_method =
@@ -357,6 +353,7 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
                        && !iinfo->is_constructor;
        }
        if (iinfo->is_method) {
+               /* Add one for the implicit invocant arg. */
                iinfo->n_invoke_args++;
        }
 
@@ -367,13 +364,6 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
               iinfo->n_args, iinfo->n_invoke_args, iinfo->n_given_args,
               iinfo->is_constructor, iinfo->is_method);
 
-       iinfo->return_type_info =
-               g_callable_info_get_return_type ((GICallableInfo *) info);
-       iinfo->has_return_value =
-               GI_TYPE_TAG_VOID != g_type_info_get_tag (iinfo->return_type_info);
-       iinfo->return_type_ffi = g_type_info_get_ffi_type (iinfo->return_type_info);
-       iinfo->return_type_transfer = g_callable_info_get_caller_owns ((GICallableInfo *) info);
-
        /* allocate enough space for all args in both the out and in lists.
         * we'll only use as much as we need.  since function argument lists
         * are typically small, this shouldn't be a big problem. */
@@ -384,7 +374,6 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
                iinfo->out_arg_infos = gperl_alloc_temp (sizeof (GITypeInfo*) * n);
                iinfo->arg_types = gperl_alloc_temp (sizeof (ffi_type *) * n);
                iinfo->args = gperl_alloc_temp (sizeof (gpointer) * n);
-               iinfo->aux_args = gperl_alloc_temp (sizeof (GIArgument) * n);
                iinfo->is_automatic_arg = gperl_alloc_temp (sizeof (gboolean) * n);
        }
 
@@ -393,7 +382,7 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
 
        /* Make a first pass to mark args that are filled in automatically, and
         * thus have no counterpart on the Perl side. */
-       for (i = 0 ; i < iinfo->n_args ; i++) {
+       for (i = 0 ; i < iinfo->base.n_args ; i++) {
                GIArgInfo * arg_info =
                        g_callable_info_get_arg ((GICallableInfo *) info, i);
                GITypeInfo * arg_type = g_arg_info_get_type (arg_info);
@@ -427,7 +416,7 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
        /* Make another pass to count the expected args. */
        iinfo->n_expected_args = iinfo->method_offset;
        iinfo->n_nullable_args = 0;
-       for (i = 0 ; i < iinfo->n_args ; i++) {
+       for (i = 0 ; i < iinfo->base.n_args ; i++) {
                GIArgInfo * arg_info =
                        g_callable_info_get_arg ((GICallableInfo *) info, i);
                GITypeInfo * arg_type = g_arg_info_get_type (arg_info);
@@ -451,8 +440,8 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
 
        /* If the return value is an array which comes with an outbound length
         * arg, then mark that length arg as automatic, too. */
-       if (g_type_info_get_tag (iinfo->return_type_info) == GI_TYPE_TAG_ARRAY) {
-               gint pos = g_type_info_get_array_length (iinfo->return_type_info);
+       if (g_type_info_get_tag (iinfo->base.return_type_info) == GI_TYPE_TAG_ARRAY) {
+               gint pos = g_type_info_get_array_length (iinfo->base.return_type_info);
                if (pos >= 0) {
                        GIArgInfo * arg_info =
                                g_callable_info_get_arg ((GICallableInfo *) info, pos);
@@ -468,38 +457,29 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
         * descendants receive from gobject-introspection: values of this type
         * are always marked transfer=none, even for constructors. */
        if (iinfo->is_constructor &&
-           g_type_info_get_tag (iinfo->return_type_info) == GI_TYPE_TAG_INTERFACE)
+           g_type_info_get_tag (iinfo->base.return_type_info) == GI_TYPE_TAG_INTERFACE)
        {
-               GIBaseInfo * interface = g_type_info_get_interface (iinfo->return_type_info);
+               GIBaseInfo * interface = g_type_info_get_interface (iinfo->base.return_type_info);
                if (GI_IS_REGISTERED_TYPE_INFO (interface) &&
                    g_type_is_a (get_gtype (interface),
                                 G_TYPE_INITIALLY_UNOWNED))
                {
-                       iinfo->return_type_transfer = GI_TRANSFER_EVERYTHING;
+                       iinfo->base.return_type_transfer = GI_TRANSFER_EVERYTHING;
                }
                g_base_info_unref ((GIBaseInfo *) interface);
        }
 }
 
 static void
-_clear_c_invocation_info (GPerlI11nInvocationInfo *iinfo)
+_clear_c_invocation_info (GPerlI11nCInvocationInfo *iinfo)
 {
-       g_slist_free (iinfo->free_after_call);
-
-       /* The actual callback infos might be needed later, so we cannot free
-        * them here. */
-       g_slist_free (iinfo->callback_infos);
-
-       g_slist_foreach (iinfo->array_infos, (GFunc) g_free, NULL);
-       g_slist_free (iinfo->array_infos);
-
-       g_base_info_unref ((GIBaseInfo *) iinfo->return_type_info);
+       clear_invocation_info ((GPerlI11nInvocationInfo *) iinfo);
 }
 
 /* ------------------------------------------------------------------------- */
 
 static gchar *
-_format_target (GPerlI11nInvocationInfo *iinfo)
+_format_target (GPerlI11nCInvocationInfo *iinfo)
 {
        gchar *caller = NULL;
        if (iinfo->target_package && iinfo->target_namespace && iinfo->target_function) {
@@ -513,14 +493,14 @@ _format_target (GPerlI11nInvocationInfo *iinfo)
                                      NULL);
        } else {
                caller = g_strconcat ("Callable ",
-                                     g_base_info_get_name (iinfo->interface),
+                                     g_base_info_get_name (iinfo->base.interface),
                                      NULL);
        }
        return caller;
 }
 
 static void
-_check_n_args (GPerlI11nInvocationInfo *iinfo)
+_check_n_args (GPerlI11nCInvocationInfo *iinfo)
 {
        if (iinfo->n_expected_args != iinfo->n_given_args) {
                /* Avoid the cost of formatting the target until we know we
@@ -547,12 +527,12 @@ _check_n_args (GPerlI11nInvocationInfo *iinfo)
 static void
 _handle_automatic_arg (guint pos,
                        GIArgument * arg,
-                       GPerlI11nInvocationInfo * invocation_info)
+                       GPerlI11nCInvocationInfo * invocation_info)
 {
        GSList *l;
 
        /* array length */
-       for (l = invocation_info->array_infos; l != NULL; l = l->next) {
+       for (l = invocation_info->base.array_infos; l != NULL; l = l->next) {
                GPerlI11nArrayInfo *ainfo = l->data;
                if (((gint) pos) == ainfo->length_pos) {
                        dwarn ("  setting automatic arg %d (array length) to %"G_GSIZE_FORMAT"\n",
@@ -564,7 +544,7 @@ _handle_automatic_arg (guint pos,
        }
 
        /* callback destroy notify */
-       for (l = invocation_info->callback_infos; l != NULL; l = l->next) {
+       for (l = invocation_info->base.callback_infos; l != NULL; l = l->next) {
                GPerlI11nPerlCallbackInfo *cinfo = l->data;
                if (((gint) pos) == cinfo->destroy_pos) {
                        dwarn ("  setting automatic arg %d (destroy notify for calllback %p)\n",
@@ -623,36 +603,3 @@ _allocate_out_mem (GITypeInfo *arg_type)
                return NULL;
        }
 }
-
-/* ------------------------------------------------------------------------- */
-
-typedef struct {
-       GFunc func;
-       gpointer data;
-} FreeClosure;
-
-static void
-free_after_call (GPerlI11nInvocationInfo *iinfo, GFunc func, gpointer data)
-{
-       FreeClosure *closure = g_new (FreeClosure, 1);
-       closure->func = func;
-       closure->data = data;
-       iinfo->free_after_call
-               = g_slist_prepend (iinfo->free_after_call, closure);
-}
-
-static void
-_invoke_free_closure (FreeClosure *closure)
-{
-       closure->func (closure->data, NULL);
-       g_free (closure);
-}
-
-static void
-_invoke_free_after_call_handlers (GPerlI11nInvocationInfo *iinfo)
-{
-       g_slist_foreach (iinfo->free_after_call,
-                        (GFunc) _invoke_free_closure, NULL);
-       g_slist_free (iinfo->free_after_call);
-       iinfo->free_after_call = NULL;
-}
diff --git a/gperl-i11n-invoke-perl.c b/gperl-i11n-invoke-perl.c
index d07a353..2e74372 100644
--- a/gperl-i11n-invoke-perl.c
+++ b/gperl-i11n-invoke-perl.c
@@ -1,16 +1,16 @@
 /* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
 
-static void _prepare_perl_invocation_info (GPerlI11nInvocationInfo *iinfo,
+static void _prepare_perl_invocation_info (GPerlI11nPerlInvocationInfo *iinfo,
                                            GICallableInfo *info,
                                            gpointer *args);
-static void _clear_perl_invocation_info (GPerlI11nInvocationInfo *iinfo);
+static void _clear_perl_invocation_info (GPerlI11nPerlInvocationInfo *iinfo);
 
 static void
 invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata)
 {
        GPerlI11nPerlCallbackInfo *info;
        GICallableInfo *cb_interface;
-       GPerlI11nInvocationInfo iinfo = {0,};
+       GPerlI11nPerlInvocationInfo iinfo;
        guint args_offset = 0, i;
        guint in_inout;
        guint n_return_values, n_returned;
@@ -50,7 +50,7 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
        /* convert the implicit instance argument and push the first SV onto
         * the stack; depending on the "swap" setting, this might be the
         * instance or the user data.  this is only relevant for signals. */
-       if (iinfo.is_signal) {
+       if (iinfo.base.is_signal) {
                SV *instance_sv, *data_sv;
                args_offset = 1;
                instance_sv = SAVED_STACK_SV (instance_pointer_to_sv (
@@ -72,13 +72,13 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
         * suitable converters; push in and in-out arguments onto the perl
         * stack */
        in_inout = 0;
-       for (i = 0; i < iinfo.n_args; i++) {
+       for (i = 0; i < iinfo.base.n_args; i++) {
                GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
                GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
                GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
                GIDirection direction = g_arg_info_get_direction (arg_info);
 
-               iinfo.current_pos = i;
+               iinfo.base.current_pos = i;
 
                dwarn ("arg info: %s (%p)\n"
                       "  direction: %d\n"
@@ -113,7 +113,7 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
                                ? *((gpointer *) args[i+args_offset])
                                : args[i+args_offset];
                        raw_to_arg (raw, &arg, arg_type);
-                       sv = SAVED_STACK_SV (arg_to_sv (&arg, arg_type, transfer, &iinfo));
+                       sv = SAVED_STACK_SV (arg_to_sv (&arg, arg_type, transfer, &iinfo.base));
                        /* If arg_to_sv returns NULL, we take that as 'skip
                         * this argument'; happens for GDestroyNotify, for
                         * example. */
@@ -149,7 +149,7 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
 
        /* determine suitable Perl call context */
        context = G_VOID | G_DISCARD;
-       if (iinfo.has_return_value) {
+       if (iinfo.base.has_return_value) {
                context = in_inout > 0
                  ? G_ARRAY
                  : G_SCALAR;
@@ -162,7 +162,7 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
        }
 
        /* do the call, demand #in-out+#out+#return-value return values */
-       n_return_values = iinfo.has_return_value
+       n_return_values = iinfo.base.has_return_value
          ? in_inout + 1
          : in_inout;
        n_returned = info->sub_name
@@ -194,7 +194,7 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
                }
 
                out_index = 0;
-               for (i = 0; i < iinfo.n_args; i++) {
+               for (i = 0; i < iinfo.base.n_args; i++) {
                        GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
                        GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
                        GIDirection direction = g_arg_info_get_direction (arg_info);
@@ -226,7 +226,7 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
                                }
                                sv_to_arg (returned_values[out_index], &tmp_arg,
                                           arg_info, arg_type,
-                                          transfer, may_be_null, &iinfo);
+                                          transfer, may_be_null, &iinfo.base);
                                if (!is_caller_allocated) {
                                        arg_to_raw (&tmp_arg, out_pointer, arg_type);
                                }
@@ -241,14 +241,14 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
        }
 
        /* store return value in resp, if any */
-       if (iinfo.has_return_value) {
+       if (iinfo.base.has_return_value) {
                GIArgument arg;
                GITypeInfo *type_info;
                GITransfer transfer;
                gboolean may_be_null;
 
-               type_info = iinfo.return_type_info;
-               transfer = iinfo.return_type_transfer;
+               type_info = iinfo.base.return_type_info;
+               transfer = iinfo.base.return_type_transfer;
                may_be_null = g_callable_info_may_return_null (cb_interface); /* FIXME */
 
                dwarn ("ret type: %p\n"
@@ -261,7 +261,7 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
                       transfer);
 
                sv_to_arg (POPs, &arg, NULL, type_info,
-                          transfer, may_be_null, &iinfo);
+                          transfer, may_be_null, &iinfo.base);
                arg_to_raw (&arg, resp, type_info);
        }
 
@@ -337,48 +337,30 @@ invoke_perl_signal_handler (ffi_cif* cif, gpointer resp, gpointer* args, gpointe
 /* -------------------------------------------------------------------------- */
 
 static void
-_prepare_perl_invocation_info (GPerlI11nInvocationInfo *iinfo,
+_prepare_perl_invocation_info (GPerlI11nPerlInvocationInfo *iinfo,
                                GICallableInfo *info,
                                gpointer *args)
 {
        guint i;
 
+       prepare_invocation_info ((GPerlI11nInvocationInfo *) iinfo, info);
+
        dwarn ("Perl invoke: %s\n"
               "  n_args: %d\n",
               g_base_info_get_name (info),
               g_callable_info_get_n_args (info));
 
-       iinfo->interface = info;
-
        /* When invoking Perl code, we currently always use a complete
         * description of the callable (from a record field or some callback
         * typedef) for functions, vfuncs and calllbacks.  This implies that
         * there is no implicit invocant; it always appears explicitly in the
         * arg list.  For signals, however, the invocant is implicit. */
-       iinfo->is_function = GI_IS_FUNCTION_INFO (info);
-       iinfo->is_vfunc = GI_IS_VFUNC_INFO (info);
-       iinfo->is_signal = GI_IS_SIGNAL_INFO (info);
-       iinfo->is_callback = (g_base_info_get_type (info) == GI_INFO_TYPE_CALLBACK);
-       dwarn ("  is_function = %d, is_vfunc = %d, is_callback = %d, is_signal = %d\n",
-              iinfo->is_function, iinfo->is_vfunc, iinfo->is_callback, iinfo->is_signal);
-
-       iinfo->n_args = g_callable_info_get_n_args (info);
 
        /* FIXME: 'throws'? */
 
-       iinfo->return_type_info = g_callable_info_get_return_type (info);
-       iinfo->has_return_value =
-               GI_TYPE_TAG_VOID != g_type_info_get_tag (iinfo->return_type_info);
-       iinfo->return_type_transfer = g_callable_info_get_caller_owns (info);
-
-       iinfo->dynamic_stack_offset = 0;
-
        /* Find array length arguments and store their value in aux_args so
         * that array_to_sv can later fetch them. */
-       if (iinfo->n_args) {
-               iinfo->aux_args = gperl_alloc_temp (sizeof (GIArgument) * iinfo->n_args);
-       }
-       for (i = 0 ; i < iinfo->n_args ; i++) {
+       for (i = 0 ; i < iinfo->base.n_args ; i++) {
                GIArgInfo *arg_info = g_callable_info_get_arg (info, i);
                GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
                GITypeTag arg_tag = g_type_info_get_tag (arg_type);
@@ -388,7 +370,7 @@ _prepare_perl_invocation_info (GPerlI11nInvocationInfo *iinfo,
                        if (pos >= 0) {
                                GIArgInfo *length_arg_info = g_callable_info_get_arg (info, i);
                                GITypeInfo *length_arg_type = g_arg_info_get_type (arg_info);
-                               raw_to_arg (args[pos], &iinfo->aux_args[pos], length_arg_type);
+                               raw_to_arg (args[pos], &iinfo->base.aux_args[pos], length_arg_type);
                                dwarn ("  pos %d is array length => %"G_GSIZE_FORMAT"\n",
                                       pos, iinfo->aux_args[pos].v_size);
                                g_base_info_unref (length_arg_type);
@@ -402,11 +384,7 @@ _prepare_perl_invocation_info (GPerlI11nInvocationInfo *iinfo,
 }
 
 static void
-_clear_perl_invocation_info (GPerlI11nInvocationInfo *iinfo)
+_clear_perl_invocation_info (GPerlI11nPerlInvocationInfo *iinfo)
 {
-       /* The actual callback infos might be needed later, so we cannot free
-        * them here. */
-       g_slist_free (iinfo->callback_infos);
-
-       g_base_info_unref ((GIBaseInfo *) iinfo->return_type_info);
+       clear_invocation_info ((GPerlI11nInvocationInfo *) iinfo);
 }
diff --git a/gperl-i11n-invoke.c b/gperl-i11n-invoke.c
new file mode 100644
index 0000000..dadc213
--- /dev/null
+++ b/gperl-i11n-invoke.c
@@ -0,0 +1,85 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
+
+static void
+prepare_invocation_info (GPerlI11nInvocationInfo *iinfo,
+                         GICallableInfo *info)
+{
+       dwarn ("invoke: %s\n"
+              "  n_args: %d\n",
+              g_base_info_get_name (info),
+              g_callable_info_get_n_args (info));
+
+       iinfo->interface = info;
+
+       iinfo->is_function = GI_IS_FUNCTION_INFO (info);
+       iinfo->is_vfunc = GI_IS_VFUNC_INFO (info);
+       iinfo->is_callback = (g_base_info_get_type (info) == GI_INFO_TYPE_CALLBACK);
+       iinfo->is_signal = GI_IS_SIGNAL_INFO (info);
+       dwarn ("  is_function = %d, is_vfunc = %d, is_callback = %d\n",
+              iinfo->is_function, iinfo->is_vfunc, iinfo->is_callback);
+
+       iinfo->n_args = g_callable_info_get_n_args (info);
+
+       iinfo->aux_args = NULL;
+       if (iinfo->n_args) {
+               iinfo->aux_args = gperl_alloc_temp (sizeof (GIArgument) * iinfo->n_args);
+       }
+
+       iinfo->return_type_info = g_callable_info_get_return_type (info);
+       iinfo->has_return_value =
+               GI_TYPE_TAG_VOID != g_type_info_get_tag (iinfo->return_type_info);
+       iinfo->return_type_ffi = g_type_info_get_ffi_type (iinfo->return_type_info);
+       iinfo->return_type_transfer = g_callable_info_get_caller_owns (info);
+
+       iinfo->callback_infos = NULL;
+       iinfo->array_infos = NULL;
+       iinfo->free_after_call = NULL;
+}
+
+static void
+clear_invocation_info (GPerlI11nInvocationInfo *iinfo)
+{
+       g_slist_free (iinfo->free_after_call);
+
+       /* The actual callback infos might be needed later, so we cannot free
+        * them here. */
+       g_slist_free (iinfo->callback_infos);
+
+       g_slist_foreach (iinfo->array_infos, (GFunc) g_free, NULL);
+       g_slist_free (iinfo->array_infos);
+
+       g_base_info_unref ((GIBaseInfo *) iinfo->return_type_info);
+}
+
+/* ------------------------------------------------------------------------- */
+
+typedef struct {
+       GFunc func;
+       gpointer data;
+} FreeClosure;
+
+static void
+free_after_call (GPerlI11nInvocationInfo *iinfo, GFunc func, gpointer data)
+{
+       FreeClosure *closure = g_new (FreeClosure, 1);
+       closure->func = func;
+       closure->data = data;
+       iinfo->free_after_call
+               = g_slist_prepend (iinfo->free_after_call, closure);
+}
+
+static void
+_invoke_free_closure (FreeClosure *closure)
+{
+       closure->func (closure->data, NULL);
+       g_free (closure);
+}
+
+static void
+invoke_free_after_call_handlers (GPerlI11nInvocationInfo *iinfo)
+{
+       g_slist_foreach (iinfo->free_after_call,
+                        (GFunc) _invoke_free_closure, NULL);
+       g_slist_free (iinfo->free_after_call);
+       iinfo->free_after_call = NULL;
+}


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