[perl-Glib-Object-Introspection] Allow setting untyped pointers in structs



commit ede00c499ad641a191e23355e1b585ce96196cd9
Author: Torsten SchÃnfeld <kaffeetisch gmx de>
Date:   Fri Jan 25 17:42:56 2013 +0100

    Allow setting untyped pointers in structs
    
    We install an RV to the SV for raw pointer fields.  As long as the SV is kept
    alive by the users, it can later be retrieved from the field with SvRV.

 gperl-i11n-field.c       |   12 ++++++++++++
 gperl-i11n-marshal-arg.c |   23 +++++++++++++++++++----
 2 files changed, 31 insertions(+), 4 deletions(-)
---
diff --git a/gperl-i11n-field.c b/gperl-i11n-field.c
index 7174599..6c7c116 100644
--- a/gperl-i11n-field.c
+++ b/gperl-i11n-field.c
@@ -156,6 +156,18 @@ set_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer, SV *sv)
 		}
 	}
 
+	/* Neither are void pointers.  We put an RV to the SV into them, which
+	 * goes hand in hand with what get_field() is doing above via
+	 * arg_to_sv(). */
+	else if (tag == GI_TYPE_TAG_VOID &&
+	         g_type_info_is_pointer (field_type))
+	{
+		gsize 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;
+	}
+
 	else {
 		sv_to_arg (sv, &arg, NULL, field_type,
 		           transfer, TRUE, NULL);
diff --git a/gperl-i11n-marshal-arg.c b/gperl-i11n-marshal-arg.c
index a67ea70..f2d87c2 100644
--- a/gperl-i11n-marshal-arg.c
+++ b/gperl-i11n-marshal-arg.c
@@ -17,7 +17,8 @@ sv_to_arg (SV * sv,
 		/* Interfaces and void types need to be able to handle undef
 		 * separately. */
 		if (!may_be_null && tag != GI_TYPE_TAG_INTERFACE
-		                 && tag != GI_TYPE_TAG_VOID) {
+		                 && tag != GI_TYPE_TAG_VOID)
+		{
 			if (arg_info) {
 				ccroak ("undefined value for mandatory argument '%s' encountered",
 				        g_base_info_get_name ((GIBaseInfo *) arg_info));
@@ -30,6 +31,13 @@ sv_to_arg (SV * sv,
 	    case GI_TYPE_TAG_VOID:
 		/* returns NULL if no match is found */
 		arg->v_pointer = sv_to_callback_data (sv, invocation_info);
+		if (!arg->v_pointer && g_type_info_is_pointer (type_info)
+		    && gperl_sv_is_ref (sv))
+		{
+			arg->v_pointer = SvRV (sv);
+		}
+		dwarn ("    argument with no type information -> pointer %p\n",
+		       arg->v_pointer);
 		break;
 
 	    case GI_TYPE_TAG_BOOLEAN:
@@ -146,10 +154,17 @@ arg_to_sv (GIArgument * arg,
 	switch (tag) {
 	    case GI_TYPE_TAG_VOID:
 	    {
+		/* returns NULL if no match is found */
 		SV *sv = callback_data_to_sv (arg->v_pointer, iinfo);
-		dwarn ("    argument with no type information -> %s\n",
-		       sv ? "callback data" : "undef");
-		return sv ? SvREFCNT_inc (sv) : &PL_sv_undef;
+		if (sv) {
+			SvREFCNT_inc (sv);
+		} else {
+			if (arg->v_pointer && g_type_info_is_pointer (info)) {
+				sv = newRV (arg->v_pointer);
+			}
+		}
+		dwarn ("    argument with no type information -> SV %p\n", sv);
+		return sv ? sv : &PL_sv_undef;
 	    }
 
 	    case GI_TYPE_TAG_BOOLEAN:



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