[perl-Glib-Object-Introspection] Handle disguised structures



commit 50624bf27a5d639c2447a2acdb6135620e9f27d7
Author: Torsten SchÃnfeld <kaffeetisch gmx de>
Date:   Sat Aug 11 20:29:39 2012 +0200

    Handle disguised structures
    
    Such as GdkAtom.

 NEWS                        |    1 +
 gperl-i11n-marshal-struct.c |   45 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 0 deletions(-)
---
diff --git a/NEWS b/NEWS
index 0c57526..14b0b86 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Overview of changes in Glib::Object::Introspection 0.012
 ========================================================
 
 * Support more struct types when writing fields.
+* Handle disguised structures.
 
 Overview of changes in Glib::Object::Introspection 0.011
 ========================================================
diff --git a/gperl-i11n-marshal-struct.c b/gperl-i11n-marshal-struct.c
index 680e2c7..3f1f3cb 100644
--- a/gperl-i11n-marshal-struct.c
+++ b/gperl-i11n-marshal-struct.c
@@ -1,5 +1,24 @@
 /* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
 
+static gchar *
+get_struct_package (GIBaseInfo* info)
+{
+	const gchar *basename, *package, *name;
+	basename = g_base_info_get_namespace (info);
+	package = get_package_for_basename (basename);
+	g_assert (package);
+	name = g_base_info_get_name (info);
+	return g_strconcat (package, "::", name, NULL);
+}
+
+/* FIXME: Should g-i offer API for this? */
+static gboolean
+is_struct_disguised (GIBaseInfo* info)
+{
+	return 0 == g_struct_info_get_n_fields (info) &&
+	       0 == g_struct_info_get_size (info);
+}
+
 /* This may call Perl code (via get_field), so it needs to be wrapped with
  * PUTBACK/SPAGAIN by the caller. */
 static SV *
@@ -16,6 +35,18 @@ struct_to_sv (GIBaseInfo* info,
 		return &PL_sv_undef;
 	}
 
+	if (is_struct_disguised (info)) {
+		SV *sv;
+		gchar *package;
+		dwarn ("  disguised struct\n");
+		g_assert (!own);
+		package = get_struct_package (info);
+		sv = newSV (0);
+		sv_setref_pv (sv, package, pointer);
+		g_free (package);
+		return sv;
+	}
+
 	hv = newHV ();
 
 	switch (info_type) {
@@ -74,6 +105,20 @@ sv_to_struct (GITransfer transfer,
 
 	dwarn ("%s: sv %p\n", G_STRFUNC, sv);
 
+	if (!gperl_sv_is_defined (sv))
+		return NULL;
+
+	if (is_struct_disguised (info)) {
+		gchar *package;
+		dwarn ("  disguised struct\n");
+		package = get_struct_package (info);
+		if (!gperl_sv_is_ref (sv) || !sv_derived_from (sv, package))
+			croak("Cannot convert scalar %p to an object of type %s",
+			      sv, package);
+		g_free (package);
+		return INT2PTR (void *, SvIV ((SV *) SvRV (sv)));
+	}
+
 	if (!gperl_sv_is_hash_ref (sv))
 		ccroak ("need a hash ref to convert to struct of type %s",
 		       g_base_info_get_name (info));



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