[perl-Glib-Object-Introspection/ppc64-fixes: 1/6] Factor our the common parts of the invocation infos for C and Perl code
- From: Torsten Schönfeld <tsch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [perl-Glib-Object-Introspection/ppc64-fixes: 1/6] Factor our the common parts of the invocation infos for C and Perl code
- Date: Mon, 8 Sep 2014 20:29:43 +0000 (UTC)
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]