@@ -82,52 +82,80 @@ 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;
+
+ /* Information about the args from the typelib. */
+ GIArgInfo ** arg_infos;
+ GITypeInfo ** arg_types;
+
+ /* 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;
+ ffi_type ** arg_types_ffi;
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 constructor_offset;
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 +168,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 +195,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 +317,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"
@@ -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
@@ -4,7 +4,7 @@
"Glib::Object::Introspection Team <gtk-perl-list at gnome dot org>"
],
"dynamic_config" : 1,
- "generated_by" : "ExtUtils::MakeMaker version 6.86, CPAN::Meta::Converter version 2.133380",
+ "generated_by" : "ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.141520",
"license" : [
"lgpl_2_1"
],
@@ -63,7 +63,8 @@
"url" : "git://git.gnome.org/perl-Glib-Object-Introspection",
"web" : "http://git.gnome.org/browse/perl-Glib-Object-Introspection"
},
+ "x_IRC" : "irc://irc.gimp.org/#gtk-perl",
"x_MailingList" : "https://mail.gnome.org/mailman/listinfo/gtk-perl-list"
},
- "version" : "0.024"
+ "version" : "0.025"
}
@@ -3,18 +3,18 @@ abstract: 'Dynamically create Perl language bindings'
author:
- 'Glib::Object::Introspection Team <gtk-perl-list at gnome dot org>'
build_requires:
- ExtUtils::MakeMaker: 0
+ ExtUtils::MakeMaker: '0'
configure_requires:
- ExtUtils::Depends: 0.3
- ExtUtils::MakeMaker: 0
- ExtUtils::PkgConfig: 1
- Glib: 1.28
+ ExtUtils::Depends: '0.3'
+ ExtUtils::MakeMaker: '0'
+ ExtUtils::PkgConfig: '1'
+ Glib: '1.28'
dynamic_config: 1
-generated_by: 'ExtUtils::MakeMaker version 6.86, CPAN::Meta::Converter version 2.133380'
+generated_by: 'ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.141520'
license: lgpl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
- version: 1.4
+ version: '1.4'
name: Glib-Object-Introspection
no_index:
directory:
@@ -26,13 +26,14 @@ no_index:
- MY
- Glib::Object::Introspection::_FuncWrapper
requires:
- ExtUtils::Depends: 0.3
- ExtUtils::PkgConfig: 1
- Glib: 1.28
+ ExtUtils::Depends: '0.3'
+ ExtUtils::PkgConfig: '1'
+ Glib: '1.28'
resources:
+ IRC: irc://irc.gimp.org/#gtk-perl
MailingList: https://mail.gnome.org/mailman/listinfo/gtk-perl-list
bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=Glib-Object-Introspection
homepage: http://gtk2-perl.sourceforge.net
license: http://www.gnu.org/licenses/lgpl-2.1.html
repository: git://git.gnome.org/perl-Glib-Object-Introspection
-version: 0.024
+version: '0.025'
@@ -62,6 +62,7 @@ my %meta_merge = (
homepage => 'http://gtk2-perl.sourceforge.net',
x_MailingList =>
'https://mail.gnome.org/mailman/listinfo/gtk-perl-list',
+ x_IRC => "irc://irc.gimp.org/#gtk-perl",
bugtracker => {
web =>
'http://rt.cpan.org/Public/Dist/Display.html?Name=Glib-Object-Introspection',
@@ -1,3 +1,9 @@
+Overview of changes in Glib::Object::Introspection 0.025
+========================================================
+
+* Fix many argument conversion bugs on 64bit big-endian architectures.
+* Added 'x_IRC' metadata tag so MetaCPAN displays a link to the IRC channel
+
Overview of changes in Glib::Object::Introspection 0.024
========================================================
@@ -1,10 +1,10 @@
/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
-#define FILL_VALUES(values) \
+#define FILL_VALUES(values, value_type) \
{ gint i; \
for (i = 0; i < n_values; i++) { \
GIValueInfo *value_info = g_enum_info_get_value (info, i); \
- (values)[i].value = g_value_info_get_value (value_info); \
+ (values)[i].value = (value_type) g_value_info_get_value (value_info); \
/* FIXME: Can we assume that the strings will stick around long enough? */ \
(values)[i].value_nick = g_base_info_get_name (value_info); \
(values)[i].value_name = g_base_info_get_attribute (value_info, "c:identifier"); \
@@ -37,10 +37,10 @@ register_unregistered_enum (GIEnumInfo *info)
n_values = g_enum_info_get_n_values (info);
if (info_type == GI_INFO_TYPE_ENUM) {
values = g_new0 (GEnumValue, n_values+1); /* zero-terminated */
- FILL_VALUES ((GEnumValue *) values);
+ FILL_VALUES ((GEnumValue *) values, gint);
} else {
values = g_new0 (GFlagsValue, n_values+1); /* zero-terminated */
- FILL_VALUES ((GFlagsValue *) values);
+ FILL_VALUES ((GFlagsValue *) values, guint);
}
if (info_type == GI_INFO_TYPE_ENUM) {
@@ -67,7 +67,7 @@ get_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer)
g_type_info_get_tag (field_type) == GI_TYPE_TAG_INTERFACE &&
g_base_info_get_type (interface_info) == GI_INFO_TYPE_STRUCT)
{
- gsize offset;
+ gint offset;
offset = g_field_info_get_offset (field_info);
value.v_pointer = mem + offset;
sv = arg_to_sv (&value,
@@ -114,9 +114,9 @@ set_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer, SV *sv)
/* FIXME: No GIArgInfo and no GPerlI11nInvocationInfo here.
* What if the struct contains an object pointer, or a callback
* field? */
- gsize offset = g_field_info_get_offset (field_info);
+ gint offset = g_field_info_get_offset (field_info);
if (!g_type_info_is_pointer (field_type)) { /* By value */
- gssize size;
+ gsize size;
/* Enforce GI_TRANSFER_NOTHING since we will copy into
* the memory that has already been allocated inside
* 'mem' */
@@ -162,7 +162,7 @@ set_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer, SV *sv)
else if (tag == GI_TYPE_TAG_VOID &&
g_type_info_is_pointer (field_type))
{
- gsize offset = g_field_info_get_offset (field_info);
+ gint offset = g_field_info_get_offset (field_info);
sv_to_arg (sv, &arg, NULL, field_type,
transfer, TRUE, NULL);
G_STRUCT_MEMBER (gpointer, mem, offset) = arg.v_pointer;
@@ -1,19 +1,20 @@
/* -*- 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,
+ GIArgInfo * arg_info,
+ GITypeInfo * arg_type,
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 +28,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;
@@ -46,7 +47,7 @@ invoke_c_code (GICallableInfo *info,
if (iinfo.is_method) {
instance = instance_sv_to_pointer (info, ST (0 + iinfo.stack_offset));
- iinfo.arg_types[0] = &ffi_type_pointer;
+ iinfo.arg_types_ffi[0] = &ffi_type_pointer;
iinfo.args[0] = &instance;
}
@@ -54,7 +55,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;
@@ -62,28 +63,28 @@ invoke_c_code (GICallableInfo *info,
gint perl_stack_pos, ffi_stack_pos;
SV *current_sv;
- arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
- /* In case of out and in-out args, arg_type is unref'ed after
- * the function has been invoked */
- arg_type = g_arg_info_get_type (arg_info);
+ arg_info = iinfo.base.arg_infos[i];
+ arg_type = iinfo.base.arg_types[i];
transfer = g_arg_info_get_ownership_transfer (arg_info);
may_be_null = g_arg_info_may_be_null (arg_info);
#if GI_CHECK_VERSION (1, 29, 0)
is_skipped = g_arg_info_is_skip (arg_info);
#endif
- perl_stack_pos = i
- + iinfo.method_offset
- + iinfo.stack_offset
- + iinfo.dynamic_stack_offset;
- ffi_stack_pos = i
- + iinfo.method_offset;
+ perl_stack_pos = (gint) i
+ + (gint) iinfo.constructor_offset
+ + (gint) iinfo.method_offset
+ + (gint) iinfo.stack_offset
+ + iinfo.dynamic_stack_offset;
+ ffi_stack_pos = (gint) i
+ + (gint) iinfo.method_offset;
+ g_assert (perl_stack_pos >= 0 && ffi_stack_pos >= 0);
/* FIXME: Is this right? I'm confused about the relation of
* the numbers in g_callable_info_get_arg and
* 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,26 +106,24 @@ 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] =
+ iinfo.arg_types_ffi[ffi_stack_pos] =
g_type_info_get_ffi_type (arg_type);
iinfo.args[ffi_stack_pos] = &iinfo.in_args[i];
- g_base_info_unref ((GIBaseInfo *) arg_type);
break;
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;
- iinfo.arg_types[ffi_stack_pos] = &ffi_type_pointer;
+ iinfo.arg_types_ffi[ffi_stack_pos] = &ffi_type_pointer;
/* Adjust the dynamic stack offset so that this out
* argument doesn't inadvertedly eat up an in argument. */
iinfo.dynamic_stack_offset--;
@@ -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,40 +143,38 @@ 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;
+ iinfo.arg_types_ffi[ffi_stack_pos] = &ffi_type_pointer;
iinfo.args[ffi_stack_pos] = &iinfo.in_args[i];
break;
}
-
- g_base_info_unref ((GIBaseInfo *) arg_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;
+ GITypeInfo * arg_type;
if (!iinfo.is_automatic_arg[i])
continue;
- arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
+ arg_info = iinfo.base.arg_infos[i];
+ arg_type = iinfo.base.arg_types[i];
switch (g_arg_info_get_direction (arg_info)) {
case GI_DIRECTION_IN:
- _handle_automatic_arg (i, &iinfo.in_args[i], &iinfo);
+ _handle_automatic_arg (i, arg_info, arg_type, &iinfo.in_args[i], &iinfo);
break;
case GI_DIRECTION_INOUT:
- _handle_automatic_arg (i, &iinfo.aux_args[i], &iinfo);
+ _handle_automatic_arg (i, arg_info, arg_type, &iinfo.base.aux_args[i], &iinfo);
break;
case GI_DIRECTION_OUT:
/* handled later */
break;
}
- g_base_info_unref ((GIBaseInfo *) arg_info);
}
if (iinfo.throws) {
iinfo.args[iinfo.n_invoke_args - 1] = &local_error_address;
- iinfo.arg_types[iinfo.n_invoke_args - 1] = &ffi_type_pointer;
+ iinfo.arg_types_ffi[iinfo.n_invoke_args - 1] = &ffi_type_pointer;
}
/*
@@ -186,7 +183,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_ffi))
{
_clear_c_invocation_info (&iinfo);
ccroak ("Could not prepare a call interface");
@@ -206,9 +203,10 @@ 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) {
+ _clear_c_invocation_info (&iinfo);
gperl_croak_gerror (NULL, local_error);
}
@@ -219,7 +217,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 +225,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 +233,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,14 +243,13 @@ 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;
- arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
+ arg_info = iinfo.base.arg_infos[i];
#if GI_CHECK_VERSION (1, 29, 0)
if (g_arg_info_is_skip (arg_info)) {
- g_base_info_unref ((GIBaseInfo *) arg_info);
continue;
}
#endif
@@ -267,21 +264,19 @@ invoke_c_code (GICallableInfo *info,
? GI_TRANSFER_CONTAINER
: g_arg_info_get_ownership_transfer (arg_info);
sv = SAVED_STACK_SV (arg_to_sv (iinfo.out_args[i].v_pointer,
- iinfo.out_arg_infos[i],
+ iinfo.base.arg_types[i],
transfer,
- &iinfo));
+ &iinfo.base));
if (sv) {
XPUSHs (sv_2mortal (sv));
n_return_values++;
}
- g_base_info_unref ((GIBaseInfo*) iinfo.out_arg_infos[i]);
break;
}
default:
break;
}
- g_base_info_unref ((GIBaseInfo *) arg_info);
}
_clear_c_invocation_info (&iinfo);
@@ -294,7 +289,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 +299,43 @@ _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->stack_offset = (guint) internal_stack_offset;
+ g_assert (items >= iinfo->stack_offset);
+ iinfo->n_given_args = ((guint) items) - iinfo->stack_offset;
+ iinfo->n_invoke_args = iinfo->base.n_args;
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) {
- 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);
/* 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 +343,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,36 +354,30 @@ _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. */
if (iinfo->n_invoke_args) {
- gint n = iinfo->n_invoke_args;
+ guint n = iinfo->n_invoke_args;
iinfo->in_args = gperl_alloc_temp (sizeof (GIArgument) * n);
iinfo->out_args = gperl_alloc_temp (sizeof (GIArgument) * n);
- iinfo->out_arg_infos = gperl_alloc_temp (sizeof (GITypeInfo*) * n);
- iinfo->arg_types = gperl_alloc_temp (sizeof (ffi_type *) * n);
+ iinfo->arg_types_ffi = 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);
}
+ /* If we call a constructor, we skip the initial package name resulting
+ * from the "Package->new" syntax. If we call a method, we handle the
+ * invocant separately. */
+ iinfo->constructor_offset = iinfo->is_constructor ? 1 : 0;
iinfo->method_offset = iinfo->is_method ? 1 : 0;
iinfo->dynamic_stack_offset = 0;
/* 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++) {
- GIArgInfo * arg_info =
- g_callable_info_get_arg ((GICallableInfo *) info, i);
- GITypeInfo * arg_type = g_arg_info_get_type (arg_info);
+ for (i = 0 ; i < iinfo->base.n_args ; i++) {
+ GIArgInfo * arg_info = iinfo->base.arg_infos[i];
+ GITypeInfo * arg_type = iinfo->base.arg_types[i];
GITypeTag arg_tag = g_type_info_get_tag (arg_type);
if (arg_tag == GI_TYPE_TAG_ARRAY) {
@@ -419,18 +400,14 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
}
g_base_info_unref ((GIBaseInfo *) interface);
}
-
- g_base_info_unref ((GIBaseInfo *) arg_type);
- g_base_info_unref ((GIBaseInfo *) arg_info);
}
/* Make another pass to count the expected args. */
- iinfo->n_expected_args = iinfo->method_offset;
+ iinfo->n_expected_args = iinfo->constructor_offset + iinfo->method_offset;
iinfo->n_nullable_args = 0;
- for (i = 0 ; i < iinfo->n_args ; i++) {
- GIArgInfo * arg_info =
- g_callable_info_get_arg ((GICallableInfo *) info, i);
- GITypeInfo * arg_type = g_arg_info_get_type (arg_info);
+ for (i = 0 ; i < iinfo->base.n_args ; i++) {
+ GIArgInfo * arg_info = iinfo->base.arg_infos[i];
+ GITypeInfo * arg_type = iinfo->base.arg_types[i];
GITypeTag arg_tag = g_type_info_get_tag (arg_type);
gboolean is_out = GI_DIRECTION_OUT == g_arg_info_get_direction (arg_info);
gboolean is_automatic = iinfo->is_automatic_arg[i];
@@ -444,23 +421,18 @@ _prepare_c_invocation_info (GPerlI11nInvocationInfo *iinfo,
/* Callback user data may always be NULL. */
if (g_arg_info_may_be_null (arg_info) || arg_tag == GI_TYPE_TAG_VOID)
iinfo->n_nullable_args++;
-
- g_base_info_unref ((GIBaseInfo *) arg_type);
- g_base_info_unref ((GIBaseInfo *) arg_info);
}
/* 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);
+ GIArgInfo * arg_info = iinfo->base.arg_infos[pos];
if (GI_DIRECTION_OUT == g_arg_info_get_direction (arg_info)) {
dwarn (" pos %d is automatic (array length)\n", pos);
iinfo->is_automatic_arg[pos] = TRUE;
}
- g_base_info_unref (arg_info);
}
}
@@ -468,38 +440,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 +476,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
@@ -529,12 +492,12 @@ _check_n_args (GPerlI11nInvocationInfo *iinfo)
if (iinfo->n_given_args < (iinfo->n_expected_args - iinfo->n_nullable_args)) {
caller = _format_target (iinfo);
ccroak ("%s: passed too few parameters "
- "(expected %d, got %d)",
+ "(expected %u, got %u)",
caller, iinfo->n_expected_args, iinfo->n_given_args);
} else if (iinfo->n_given_args > iinfo->n_expected_args) {
caller = _format_target (iinfo);
cwarn ("*** %s: passed too many parameters "
- "(expected %d, got %d); ignoring excess",
+ "(expected %u, got %u); ignoring excess",
caller, iinfo->n_expected_args, iinfo->n_given_args);
}
if (caller)
@@ -546,25 +509,30 @@ _check_n_args (GPerlI11nInvocationInfo *iinfo)
static void
_handle_automatic_arg (guint pos,
+ GIArgInfo * arg_info,
+ GITypeInfo * arg_type,
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) {
+ SV *conversion_sv;
dwarn (" setting automatic arg %d (array length) to %"G_GSIZE_FORMAT"\n",
pos, ainfo->length);
- /* FIXME: Is it OK to always use v_size here? */
- arg->v_size = ainfo->length;
+ conversion_sv = newSVuv (ainfo->length);
+ sv_to_arg (conversion_sv, arg, arg_info, arg_type,
+ GI_TRANSFER_NOTHING, FALSE, NULL);
+ SvREFCNT_dec (conversion_sv);
return;
}
}
/* 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 +591,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;
-}
@@ -1,19 +1,24 @@
/* -*- 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 _fill_ffi_return_value (GITypeInfo *return_info,
+ gpointer resp,
+ GIArgument *arg);
+
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;
+ guint n_return_values;
+ I32 n_returned;
I32 context;
SV *first_sv = NULL, *last_sv = NULL;
dGPERL_CALLBACK_MARSHAL_SP;
@@ -50,7 +55,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 +77,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++) {
- GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
- GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
+ for (i = 0; i < iinfo.base.n_args; i++) {
+ GIArgInfo *arg_info = iinfo.base.arg_infos[i];
+ GITypeInfo *arg_type = iinfo.base.arg_types[i];
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 +118,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. */
@@ -126,9 +131,6 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
{
in_inout++;
}
-
- g_base_info_unref ((GIBaseInfo *) arg_info);
- g_base_info_unref ((GIBaseInfo *) arg_type);
}
/* push the last SV onto the stack; this might be the user data or the
@@ -149,7 +151,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,15 +164,15 @@ 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
? call_method (info->sub_name, context)
: call_sv (info->code, context);
- if (n_return_values != 0 && n_returned != n_return_values) {
+ if (n_return_values != 0 && (n_returned < 0 || ((guint) n_returned) != n_return_values)) {
ccroak ("callback returned %d values "
- "but is supposed to return %d values",
+ "but is supposed to return %u values",
n_returned, n_return_values);
}
@@ -194,16 +196,14 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
}
out_index = 0;
- for (i = 0; i < iinfo.n_args; i++) {
- GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
- GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
+ for (i = 0; i < iinfo.base.n_args; i++) {
+ GIArgInfo *arg_info = iinfo.base.arg_infos[i];
+ GITypeInfo *arg_type = iinfo.base.arg_types[i];
GIDirection direction = g_arg_info_get_direction (arg_info);
gpointer out_pointer = * (gpointer *) args[i+args_offset];
if (!out_pointer) {
dwarn ("skipping out arg %d\n", i);
- g_base_info_unref (arg_info);
- g_base_info_unref (arg_type);
continue;
}
@@ -226,29 +226,26 @@ 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);
}
out_index++;
}
-
- g_base_info_unref (arg_info);
- g_base_info_unref (arg_type);
}
g_free (returned_values);
}
/* 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,8 +258,8 @@ 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);
- arg_to_raw (&arg, resp, type_info);
+ transfer, may_be_null, &iinfo.base);
+ _fill_ffi_return_value (type_info, resp, &arg);
}
PUTBACK;
@@ -337,76 +334,120 @@ 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++) {
- GIArgInfo *arg_info = g_callable_info_get_arg (info, i);
- GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
+ for (i = 0 ; i < iinfo->base.n_args ; i++) {
+ GITypeInfo *arg_type = iinfo->base.arg_types[i];
GITypeTag arg_tag = g_type_info_get_tag (arg_type);
if (arg_tag == GI_TYPE_TAG_ARRAY) {
gint pos = g_type_info_get_array_length (arg_type);
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);
+ GITypeInfo *length_arg_type = iinfo->base.arg_types[pos];
+ 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);
- g_base_info_unref (length_arg_info);
}
}
-
- g_base_info_unref (arg_type);
- g_base_info_unref (arg_info);
}
}
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);
+ clear_invocation_info ((GPerlI11nInvocationInfo *) iinfo);
+}
+
+/* ------------------------------------------------------------------------- */
- g_base_info_unref ((GIBaseInfo *) iinfo->return_type_info);
+/* Copied from pygobject's pygi-closure.c. */
+static void
+_fill_ffi_return_value (GITypeInfo *return_info,
+ gpointer resp,
+ GIArgument *arg)
+{
+ if (!resp)
+ return;
+ switch (g_type_info_get_tag (return_info)) {
+ case GI_TYPE_TAG_BOOLEAN:
+ *((ffi_sarg *) resp) = arg->v_boolean;
+ break;
+ case GI_TYPE_TAG_INT8:
+ *((ffi_sarg *) resp) = arg->v_int8;
+ break;
+ case GI_TYPE_TAG_UINT8:
+ *((ffi_arg *) resp) = arg->v_uint8;
+ break;
+ case GI_TYPE_TAG_INT16:
+ *((ffi_sarg *) resp) = arg->v_int16;
+ break;
+ case GI_TYPE_TAG_UINT16:
+ *((ffi_arg *) resp) = arg->v_uint16;
+ break;
+ case GI_TYPE_TAG_INT32:
+ *((ffi_sarg *) resp) = arg->v_int32;
+ break;
+ case GI_TYPE_TAG_UINT32:
+ *((ffi_arg *) resp) = arg->v_uint32;
+ break;
+ case GI_TYPE_TAG_INT64:
+ *((ffi_sarg *) resp) = arg->v_int64;
+ break;
+ case GI_TYPE_TAG_UINT64:
+ *((ffi_arg *) resp) = arg->v_uint64;
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ *((gfloat *) resp) = arg->v_float;
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ *((gdouble *) resp) = arg->v_double;
+ break;
+ case GI_TYPE_TAG_GTYPE:
+ *((ffi_arg *) resp) = arg->v_size;
+ break;
+ case GI_TYPE_TAG_UNICHAR:
+ *((ffi_arg *) resp) = arg->v_uint32;
+ break;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo *interface_info;
+ interface_info = g_type_info_get_interface (return_info);
+ switch (g_base_info_get_type (interface_info)) {
+ case GI_INFO_TYPE_ENUM:
+ *(ffi_sarg *) resp = arg->v_int;
+ break;
+ case GI_INFO_TYPE_FLAGS:
+ *(ffi_arg *) resp = arg->v_uint;
+ break;
+ default:
+ *(ffi_arg *) resp = (ffi_arg) arg->v_pointer;
+ break;
+ }
+ break;
+ }
+ default:
+ *(ffi_arg *) resp = (ffi_arg) arg->v_pointer;
+ break;
+ }
}
@@ -0,0 +1,112 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
+
+static void
+prepare_invocation_info (GPerlI11nInvocationInfo *iinfo,
+ GICallableInfo *info)
+{
+ gint orig_n_args;
+ guint i;
+
+ 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);
+
+ orig_n_args = g_callable_info_get_n_args (info);
+ g_assert (orig_n_args >= 0);
+ iinfo->n_args = (guint) orig_n_args;
+
+ if (iinfo->n_args) {
+ iinfo->arg_infos = gperl_alloc_temp (sizeof (GITypeInfo*) * iinfo->n_args);
+ iinfo->arg_types = gperl_alloc_temp (sizeof (GITypeInfo*) * iinfo->n_args);
+ iinfo->aux_args = gperl_alloc_temp (sizeof (GIArgument) * iinfo->n_args);
+ } else {
+ iinfo->arg_infos = NULL;
+ iinfo->arg_types = NULL;
+ iinfo->aux_args = NULL;
+ }
+
+ for (i = 0 ; i < iinfo->n_args ; i++) {
+ iinfo->arg_infos[i] = g_callable_info_get_arg (info, (gint) i);
+ iinfo->arg_types[i] = g_arg_info_get_type (iinfo->arg_infos[i]);
+ }
+
+ 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)
+{
+ guint i;
+
+ for (i = 0 ; i < iinfo->n_args ; i++) {
+ g_base_info_unref ((GIBaseInfo *) iinfo->arg_types[i]);
+ g_base_info_unref ((GIBaseInfo *) iinfo->arg_infos[i]);
+ }
+
+ g_slist_free (iinfo->free_after_call);
+ iinfo->free_after_call = NULL;
+
+ /* The actual callback infos might be needed later, so we cannot free
+ * them here. */
+ g_slist_free (iinfo->callback_infos);
+ iinfo->callback_infos = NULL;
+
+ g_slist_foreach (iinfo->array_infos, (GFunc) g_free, NULL);
+ g_slist_free (iinfo->array_infos);
+ iinfo->array_infos = NULL;
+
+ g_base_info_unref ((GIBaseInfo *) iinfo->return_type_info);
+ iinfo->return_type_info = 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)
+{
+ /* We free the FreeClosures themselves directly after invoking them. The list
+ is freed in clear_invocation_info. */
+ g_slist_foreach (iinfo->free_after_call,
+ (GFunc) _invoke_free_closure, NULL);
+}
@@ -215,7 +215,8 @@ arg_to_sv (GIArgument * arg,
SV *sv;
gchar buffer[6];
gint length = g_unichar_to_utf8 (arg->v_uint32, buffer);
- sv = newSVpv (buffer, length);
+ g_assert (length >= 0);
+ sv = newSVpv (buffer, (STRLEN) length);
SvUTF8_on (sv);
return sv;
}
@@ -42,10 +42,14 @@ array_to_sv (GITypeInfo *info,
} else {
length = g_type_info_get_array_fixed_size (info);
if (length < 0) {
- guint length_pos = g_type_info_get_array_length (info);
+ SV *conversion_sv;
+ gint length_pos = g_type_info_get_array_length (info);
g_assert (iinfo && iinfo->aux_args);
- /* FIXME: Is it OK to always use v_size here? */
- length = iinfo->aux_args[length_pos].v_size;
+ conversion_sv = arg_to_sv (&(iinfo->aux_args[length_pos]),
+ iinfo->arg_types[length_pos],
+ GI_TRANSFER_NOTHING, NULL);
+ length = SvIV (conversion_sv);
+ SvREFCNT_dec (conversion_sv);
}
}
@@ -67,7 +71,7 @@ array_to_sv (GITypeInfo *info,
for (i = 0; i < length; i++) {
GIArgument *arg;
SV *value;
- arg = pointer + i * item_size;
+ arg = pointer + ((gsize) i) * item_size;
value = arg_to_sv (arg, param_info, item_transfer, iinfo);
if (value)
av_push (av, value);
@@ -91,7 +95,8 @@ sv_to_array (GITransfer transfer,
GITransfer item_transfer;
GITypeInfo *param_info;
GITypeTag param_tag;
- gint i, length, length_pos;
+ gint length_pos;
+ gsize i, length;
GPerlI11nArrayInfo *array_info = NULL;
GArray *array;
gpointer raw_array;
@@ -133,7 +138,7 @@ sv_to_array (GITransfer transfer,
is_zero_terminated = g_type_info_is_zero_terminated (type_info);
item_size = size_of_type_info (param_info);
- length = av_len (av) + 1;
+ length = (gsize) (av_len (av) + 1); /* av_len always returns at least -1 */
array = g_array_sized_new (is_zero_terminated, FALSE, item_size, length);
/* Arrays containing non-basic types as non-pointers need to be treated
@@ -117,7 +117,7 @@ callback_to_sv (GICallableInfo *interface, gpointer func, GPerlI11nInvocationInf
}
arg_info = g_callable_info_get_arg (invocation_info->interface,
- invocation_info->current_pos);
+ (gint) invocation_info->current_pos);
dwarn (" C callback at %d (%s)\n",
invocation_info->current_pos,
@@ -1,5 +1,8 @@
/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
+void _store_enum (GIEnumInfo * info, gint value, GIArgument * arg);
+gint _retrieve_enum (GIEnumInfo * info, GIArgument * arg);
+
static gpointer
instance_sv_to_pointer (GICallableInfo *info, SV *sv)
{
@@ -226,25 +229,27 @@ sv_to_interface (GIArgInfo * arg_info,
case GI_INFO_TYPE_ENUM:
{
+ gint value;
GType type = get_gtype ((GIRegisteredTypeInfo *) interface);
if (G_TYPE_NONE == type) {
ccroak ("Could not handle unknown enum type %s",
g_base_info_get_name (interface));
}
- /* FIXME: Check storage type? */
- arg->v_long = gperl_convert_enum (type, sv);
+ value = gperl_convert_enum (type, sv);
+ _store_enum (interface, value, arg);
break;
}
case GI_INFO_TYPE_FLAGS:
{
+ gint value;
GType type = get_gtype ((GIRegisteredTypeInfo *) interface);
if (G_TYPE_NONE == type) {
ccroak ("Could not handle unknown flags type %s",
g_base_info_get_name (interface));
}
- /* FIXME: Check storage type? */
- arg->v_long = gperl_convert_flags (type, sv);
+ value = gperl_convert_flags (type, sv);
+ _store_enum (interface, value, arg);
break;
}
@@ -312,25 +317,27 @@ interface_to_sv (GITypeInfo* info, GIArgument *arg, gboolean own, GPerlI11nInvoc
case GI_INFO_TYPE_ENUM:
{
+ gint value;
GType type = get_gtype ((GIRegisteredTypeInfo *) interface);
if (G_TYPE_NONE == type) {
ccroak ("Could not handle unknown enum type %s",
g_base_info_get_name (interface));
}
- /* FIXME: Is it right to just use v_long here? */
- sv = gperl_convert_back_enum (type, arg->v_long);
+ value = _retrieve_enum (interface, arg);
+ sv = gperl_convert_back_enum (type, value);
break;
}
case GI_INFO_TYPE_FLAGS:
{
+ gint value;
GType type = get_gtype ((GIRegisteredTypeInfo *) interface);
if (G_TYPE_NONE == type) {
ccroak ("Could not handle unknown flags type %s",
g_base_info_get_name (interface));
}
- /* FIXME: Is it right to just use v_long here? */
- sv = gperl_convert_back_flags (type, arg->v_long);
+ value = _retrieve_enum (interface, arg);
+ sv = gperl_convert_back_flags (type, value);
break;
}
@@ -348,3 +355,91 @@ interface_to_sv (GITypeInfo* info, GIArgument *arg, gboolean own, GPerlI11nInvoc
return sv;
}
+
+/* ------------------------------------------------------------------------- */
+
+void
+_store_enum (GIEnumInfo * info, gint value, GIArgument * arg)
+{
+ GITypeTag tag = g_enum_info_get_storage_type (info);
+ switch (tag) {
+ case GI_TYPE_TAG_BOOLEAN:
+ arg->v_boolean = (gboolean) value;
+ break;
+
+ case GI_TYPE_TAG_INT8:
+ arg->v_int8 = (gint8) value;
+ break;
+
+ case GI_TYPE_TAG_UINT8:
+ arg->v_uint8 = (guint8) value;
+ break;
+
+ case GI_TYPE_TAG_INT16:
+ arg->v_int16 = (gint16) value;
+ break;
+
+ case GI_TYPE_TAG_UINT16:
+ arg->v_uint16 = (guint16) value;
+ break;
+
+ case GI_TYPE_TAG_INT32:
+ arg->v_int32 = (gint32) value;
+ break;
+
+ case GI_TYPE_TAG_UINT32:
+ arg->v_uint32 = (guint32) value;
+ break;
+
+ case GI_TYPE_TAG_INT64:
+ arg->v_int64 = (gint64) value;
+ break;
+
+ case GI_TYPE_TAG_UINT64:
+ arg->v_uint64 = (guint64) value;
+ break;
+
+ default:
+ ccroak ("Unhandled enumeration type %s (%d) encountered",
+ g_type_tag_to_string (tag), tag);
+ }
+}
+
+gint
+_retrieve_enum (GIEnumInfo * info, GIArgument * arg)
+{
+ GITypeTag tag = g_enum_info_get_storage_type (info);
+ switch (tag) {
+ case GI_TYPE_TAG_BOOLEAN:
+ return (gint) arg->v_boolean;
+
+ case GI_TYPE_TAG_INT8:
+ return (gint) arg->v_int8;
+
+ case GI_TYPE_TAG_UINT8:
+ return (gint) arg->v_uint8;
+
+ case GI_TYPE_TAG_INT16:
+ return (gint) arg->v_int16;
+
+ case GI_TYPE_TAG_UINT16:
+ return (gint) arg->v_uint16;
+
+ case GI_TYPE_TAG_INT32:
+ return (gint) arg->v_int32;
+
+ case GI_TYPE_TAG_UINT32:
+ return (gint) arg->v_uint32;
+
+ case GI_TYPE_TAG_INT64:
+ return (gint) arg->v_int64;
+
+ case GI_TYPE_TAG_UINT64:
+ return (gint) arg->v_uint64;
+
+ default:
+ ccroak ("Unhandled enumeration type %s (%d) encountered",
+ g_type_tag_to_string (tag), tag);
+ return 0;
+ }
+}
@@ -19,7 +19,7 @@ use strict;
use warnings;
use Glib;
-our $VERSION = '0.024';
+our $VERSION = '0.025';
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
@@ -5,15 +5,19 @@ BEGIN { require './t/inc/setup.pl' };
use strict;
use warnings;
-plan tests => 5;
+plan tests => 8;
{
is (Regress::test_int8 (-127), -127);
+ isa_ok (Regress::TestObj->constructor, 'Regress::TestObj');
}
{
is (eval { Regress::test_int8 () }, undef);
like ($@, qr/too few/);
+
+ is (eval { Regress::TestObj::constructor }, undef);
+ like ($@, qr/too few/);
}
{