[perl-Glib-Object-Introspection] Support caller-allocated out args in callbacks



commit 16239095cb4e6e9d2bf252ff5eeec853a048f00a
Author: Torsten SchÃnfeld <kaffeetisch gmx de>
Date:   Wed Oct 12 16:18:59 2011 +0200

    Support caller-allocated out args in callbacks
    
    The GtkCellRenderer vfunc get_aligned_area is an example.

 gperl-i11n-invoke-perl.c       |    8 +++++++-
 gperl-i11n-marshal-arg.c       |    2 --
 gperl-i11n-marshal-interface.c |   24 +++++++++++++++++++-----
 3 files changed, 26 insertions(+), 8 deletions(-)
---
diff --git a/gperl-i11n-invoke-perl.c b/gperl-i11n-invoke-perl.c
index 97dbfa8..aa8fa91 100644
--- a/gperl-i11n-invoke-perl.c
+++ b/gperl-i11n-invoke-perl.c
@@ -157,10 +157,16 @@ invoke_callback (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata)
 				GIArgument tmp_arg;
 				GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
 				gboolean may_be_null = g_arg_info_may_be_null (arg_info);
+				gboolean is_caller_allocated = g_arg_info_is_caller_allocates (arg_info);
+				if (is_caller_allocated) {
+					tmp_arg.v_pointer = out_pointer;
+				}
 				sv_to_arg (returned_values[out_index], &tmp_arg,
 				           arg_info, arg_type,
 				           transfer, may_be_null, NULL);
-				arg_to_raw (&tmp_arg, out_pointer, arg_type);
+				if (!is_caller_allocated) {
+					arg_to_raw (&tmp_arg, out_pointer, arg_type);
+				}
 				out_index++;
 			}
 
diff --git a/gperl-i11n-marshal-arg.c b/gperl-i11n-marshal-arg.c
index 7d0e6ca..bbf8c70 100644
--- a/gperl-i11n-marshal-arg.c
+++ b/gperl-i11n-marshal-arg.c
@@ -11,8 +11,6 @@ sv_to_arg (SV * sv,
 {
 	GITypeTag tag = g_type_info_get_tag (type_info);
 
-        memset (arg, 0, sizeof (GIArgument));
-
 	if (!gperl_sv_is_defined (sv))
 		/* Interfaces and void types need to be able to handle undef
 		 * separately. */
diff --git a/gperl-i11n-marshal-interface.c b/gperl-i11n-marshal-interface.c
index 773e0ee..7dea8c0 100644
--- a/gperl-i11n-marshal-interface.c
+++ b/gperl-i11n-marshal-interface.c
@@ -76,7 +76,9 @@ sv_to_interface (GIArgInfo * arg_info,
 	    case GI_INFO_TYPE_STRUCT:
 	    case GI_INFO_TYPE_BOXED:
 	    {
-		/* FIXME: What about pass-by-value here? */
+		gboolean need_value_semantics =
+			arg_info && g_arg_info_is_caller_allocates (arg_info)
+			&& !g_type_info_is_pointer (type_info);
 		GType type = g_registered_type_info_get_g_type (
 		               (GIRegisteredTypeInfo *) interface);
 		if (!type || type == G_TYPE_NONE) {
@@ -84,6 +86,7 @@ sv_to_interface (GIArgInfo * arg_info,
 				? g_arg_info_get_ownership_transfer (arg_info)
 				: GI_TRANSFER_NOTHING;
 			dwarn ("    unboxed type\n");
+			g_assert (!need_value_semantics);
 			arg->v_pointer = sv_to_struct (transfer,
 			                               interface,
 			                               info_type,
@@ -91,17 +94,28 @@ sv_to_interface (GIArgInfo * arg_info,
 		} else if (type == G_TYPE_CLOSURE) {
 			/* FIXME: User cannot supply user data. */
 			dwarn ("    closure type\n");
+			g_assert (!need_value_semantics);
 			arg->v_pointer = gperl_closure_new (sv, NULL, FALSE);
 		} else if (type == G_TYPE_VALUE) {
 			dwarn ("    value type\n");
+			g_assert (!need_value_semantics);
 			arg->v_pointer = SvGValueWrapper (sv);
 			if (!arg->v_pointer)
 				ccroak ("Cannot convert arbitrary SV to GValue");
 		} else {
-			dwarn ("    boxed type: %s (%d)\n",
-			       g_type_name (type), type);
-			/* FIXME: Check transfer setting. */
-			arg->v_pointer = gperl_get_boxed_check (sv, type);
+			dwarn ("    boxed type: %s, name=%s, caller-allocates=%d, is-pointer=%d\n",
+			       g_type_name (type),
+			       g_base_info_get_name (interface),
+			       g_arg_info_is_caller_allocates (arg_info),
+			       g_type_info_is_pointer (type_info));
+			if (need_value_semantics) {
+				gsize n_bytes = g_struct_info_get_size (interface);
+				gpointer mem = gperl_get_boxed_check (sv, type);
+				g_memmove (arg->v_pointer, mem, n_bytes);
+			} else {
+				/* FIXME: Check transfer setting. */
+				arg->v_pointer = gperl_get_boxed_check (sv, type);
+			}
 		}
 		break;
 	    }



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