diff -up -ru gobject-introspection-1.31.1.orig/girepository/gicallableinfo.c gobject-introspection-1.31.1/girepository/gicallableinfo.c
--- gobject-introspection-1.31.1.orig/girepository/gicallableinfo.c	2011-11-23 20:48:44.000000000 +0100
+++ gobject-introspection-1.31.1/girepository/gicallableinfo.c	2012-01-27 17:08:14.000000000 +0100
@@ -359,6 +359,84 @@ g_callable_info_iterate_return_attribute
   return TRUE;
 }
 
+/* Extract the correct bits from an ffi_arg return value into
+ * GIArgument: https://bugzilla.gnome.org/show_bug.cgi?id=665152
+ *
+ * Also see the ffi_call man page - the storage requirements for return
+ * values are "special".
+ */
+union GiFFIReturnValue {
+    ffi_arg  rv_ffi_arg;
+    ffi_sarg rv_ffi_sarg;
+    guint64  rv_u64;
+    gint64   rv_s64;
+    float    rv_float;
+    double   rv_double;
+};
+static void
+set_gargument_from_ffi_return_value (GITypeInfo                  *return_info,
+                                     GIArgument                  *return_value,
+                                     union GiFFIReturnValue      *value)
+{
+    switch (g_type_info_get_tag (return_info)) {
+    case GI_TYPE_TAG_INT8:
+        return_value->v_int8 = (gint8) value->rv_ffi_sarg;
+        break;
+    case GI_TYPE_TAG_UINT8:
+        return_value->v_uint8 = (guint8) value->rv_ffi_arg;
+        break;
+    case GI_TYPE_TAG_INT16:
+        return_value->v_int16 = (gint16) value->rv_ffi_sarg;
+        break;
+    case GI_TYPE_TAG_UINT16:
+        return_value->v_uint16 = (guint16) value->rv_ffi_arg;
+        break;
+    case GI_TYPE_TAG_INT32:
+        return_value->v_int32 = (gint32) value->rv_ffi_sarg;
+        break;
+    case GI_TYPE_TAG_UINT32:
+    case GI_TYPE_TAG_BOOLEAN:
+    case GI_TYPE_TAG_UNICHAR:
+        return_value->v_uint32 = (guint32) value->rv_ffi_arg;
+                        
+        break;
+    case GI_TYPE_TAG_INT64:
+        return_value->v_int64 = (gint64) value->rv_s64;
+        break;
+    case GI_TYPE_TAG_UINT64:
+        return_value->v_uint64 = (guint64) value->rv_u64;
+        break;
+    case GI_TYPE_TAG_FLOAT:
+        return_value->v_float = value->rv_float;
+        break;
+    case GI_TYPE_TAG_DOUBLE:
+        return_value->v_double = value->rv_double;
+        break;
+    case GI_TYPE_TAG_INTERFACE:
+        {
+            GIBaseInfo* interface_info;
+            GIInfoType interface_type;
+
+            interface_info = g_type_info_get_interface(return_info);
+            interface_type = g_base_info_get_type(interface_info);
+
+            switch(interface_type) {
+            case GI_INFO_TYPE_ENUM:
+            case GI_INFO_TYPE_FLAGS:
+                return_value->v_int32 = (gint32) value->rv_ffi_sarg;
+                break;
+            default:
+                return_value->v_pointer = (gpointer) value->rv_ffi_arg;
+                break;
+            }
+        }
+        break;
+    default:
+        return_value->v_pointer = (gpointer) value->rv_ffi_arg;
+        break;
+    }
+}
+
 gboolean
 _g_callable_info_invoke (GIFunctionInfo *info,
                          gpointer          function,
@@ -375,16 +453,20 @@ _g_callable_info_invoke (GIFunctionInfo
   ffi_type *rtype;
   ffi_type **atypes;
   GITypeInfo *tinfo;
+  GITypeInfo *rinfo;
+  GITypeTag rtag;
   GIArgInfo *ainfo;
   gint n_args, n_invoke_args, in_pos, out_pos, i;
   gpointer *args;
   gboolean success = FALSE;
   GError *local_error = NULL;
   gpointer error_address = &local_error;
+  union GiFFIReturnValue ffi_return_value;
+  gpointer return_value_p; /* Will point inside the union return_value */
 
-  tinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
-  rtype = g_type_info_get_ffi_type (tinfo);
-  g_base_info_unref ((GIBaseInfo *)tinfo);
+  rinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
+  rtype = g_type_info_get_ffi_type (rinfo);
+  rtag = g_type_info_get_tag(rinfo);
 
   in_pos = 0;
   out_pos = 0;
@@ -515,7 +597,23 @@ _g_callable_info_invoke (GIFunctionInfo
     goto out;
 
   g_return_val_if_fail (return_value, FALSE);
-  ffi_call (&cif, function, return_value, args);
+  /* See comment for GiFFIReturnValue above */
+  switch (rtag)
+    {
+    case GI_TYPE_TAG_FLOAT:
+      return_value_p = &ffi_return_value.rv_float;
+      break;
+    case GI_TYPE_TAG_DOUBLE:
+      return_value_p = &ffi_return_value.rv_double;
+      break;
+    case GI_TYPE_TAG_INT64:
+    case GI_TYPE_TAG_UINT64:
+      return_value_p = &ffi_return_value.rv_u64;
+      break;
+    default:
+      return_value_p = &ffi_return_value.rv_ffi_arg;
+    }
+  ffi_call (&cif, function, return_value_p, args);
 
   if (local_error)
     {
@@ -524,8 +622,10 @@ _g_callable_info_invoke (GIFunctionInfo
     }
   else
     {
+      set_gargument_from_ffi_return_value(rinfo, return_value, &ffi_return_value);
       success = TRUE;
     }
  out:
+  g_base_info_unref ((GIBaseInfo *)rinfo);
   return success;
 }
diff -up -ru gobject-introspection-1.31.1.orig/girepository/ginvoke.c gobject-introspection-1.31.1/girepository/ginvoke.c
--- gobject-introspection-1.31.1.orig/girepository/ginvoke.c	2011-11-23 20:48:44.000000000 +0100
+++ gobject-introspection-1.31.1/girepository/ginvoke.c	2012-01-27 17:31:48.000000000 +0100
@@ -87,57 +87,134 @@ value_to_ffi_type (const GValue *gvalue,
   return rettype;
 }
 
+/* Extract the correct bits from an ffi_arg return value into
+ * GIArgument: https://bugzilla.gnome.org/show_bug.cgi?id=665152
+ *
+ * Also see the ffi_call man page - the storage requirements for return
+ * values are "special".
+ */
+union FFIReturnValue {
+    ffi_arg  rv_ffi_arg;
+    ffi_sarg rv_ffi_sarg;
+    guint64  rv_u64;
+    gint64   rv_s64;
+    float    rv_float;
+    double   rv_double;
+};
+
+static ffi_type *
+g_value_to_ffi_return_type (const GValue *gvalue,
+			    const union FFIReturnValue *ffi_value,
+			    gpointer *value)
+{
+  ffi_type *rettype = NULL;
+  GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
+  g_assert (type != G_TYPE_INVALID);
+
+  *value = (gpointer)&(ffi_value->rv_ffi_arg);
+
+  switch (type) {
+  case G_TYPE_CHAR:
+    rettype = &ffi_type_sint8;
+    break;
+  case G_TYPE_UCHAR:
+    rettype = &ffi_type_uint8;
+    break;
+  case G_TYPE_BOOLEAN:
+  case G_TYPE_INT:
+    rettype = &ffi_type_sint;
+    break;
+  case G_TYPE_UINT:
+    rettype = &ffi_type_uint;
+    break;
+  case G_TYPE_STRING:
+  case G_TYPE_OBJECT:
+  case G_TYPE_BOXED:
+  case G_TYPE_POINTER:
+    rettype = &ffi_type_pointer;
+    break;
+  case G_TYPE_FLOAT:
+    rettype = &ffi_type_float;
+    *value = (gpointer)&(ffi_value->rv_float);
+    break;
+  case G_TYPE_DOUBLE:
+    rettype = &ffi_type_double;
+    *value = (gpointer)&(ffi_value->rv_double);
+    break;
+  case G_TYPE_LONG:
+    rettype = &ffi_type_slong;
+    break;
+  case G_TYPE_ULONG:
+    rettype = &ffi_type_ulong;
+    break;
+  case G_TYPE_INT64:
+    rettype = &ffi_type_sint64;
+    *value = (gpointer)&(ffi_value->rv_s64);
+    break;
+  case G_TYPE_UINT64:
+    rettype = &ffi_type_uint64;
+    *value = (gpointer)&(ffi_value->rv_u64);
+    break;
+  default:
+    rettype = &ffi_type_pointer;
+    *value = NULL;
+    g_warning ("Unsupported fundamental type: %s", g_type_name (type));
+    break;
+  }
+  return rettype;
+}
+
 static void
-value_from_ffi_type (GValue *gvalue, gpointer *value)
+g_value_from_ffi_value (GValue *gvalue, const union FFIReturnValue *value)
 {
-  switch (g_type_fundamental (G_VALUE_TYPE (gvalue)))
-    {
-    case G_TYPE_INT:
-      g_value_set_int (gvalue, *(gint*)value);
+  switch (g_type_fundamental (G_VALUE_TYPE (gvalue))) {
+  case G_TYPE_INT:
+      g_value_set_int (gvalue, (gint)value->rv_ffi_sarg);
       break;
-    case G_TYPE_FLOAT:
-      g_value_set_float (gvalue, *(gfloat*)value);
+  case G_TYPE_FLOAT:
+      g_value_set_float (gvalue, (gfloat)value->rv_float);
       break;
-    case G_TYPE_DOUBLE:
-      g_value_set_double (gvalue, *(gdouble*)value);
+  case G_TYPE_DOUBLE:
+      g_value_set_double (gvalue, (gdouble)value->rv_double);
       break;
-    case G_TYPE_BOOLEAN:
-      g_value_set_boolean (gvalue, *(gboolean*)value);
+  case G_TYPE_BOOLEAN:
+      g_value_set_boolean (gvalue, (gboolean)value->rv_ffi_arg);
       break;
-    case G_TYPE_STRING:
-      g_value_set_string (gvalue, *(gchar**)value);
+  case G_TYPE_STRING:
+      g_value_set_string (gvalue, (gchar*)value->rv_ffi_arg);
       break;
-    case G_TYPE_CHAR:
-      g_value_set_char (gvalue, *(gchar*)value);
+  case G_TYPE_CHAR:
+      g_value_set_char (gvalue, (gchar)value->rv_ffi_sarg);
       break;
-    case G_TYPE_UCHAR:
-      g_value_set_uchar (gvalue, *(guchar*)value);
+  case G_TYPE_UCHAR:
+      g_value_set_uchar (gvalue, (guchar)value->rv_ffi_arg);
       break;
-    case G_TYPE_UINT:
-      g_value_set_uint (gvalue, *(guint*)value);
+  case G_TYPE_UINT:
+      g_value_set_uint (gvalue, (guint)value->rv_ffi_arg);
       break;
-    case G_TYPE_POINTER:
-      g_value_set_pointer (gvalue, *(gpointer*)value);
+  case G_TYPE_POINTER:
+      g_value_set_pointer (gvalue, (gpointer)value->rv_ffi_arg);
       break;
-    case G_TYPE_LONG:
-      g_value_set_long (gvalue, *(glong*)value);
+  case G_TYPE_LONG:
+      g_value_set_long (gvalue, (glong)value->rv_ffi_sarg);
       break;
-    case G_TYPE_ULONG:
-      g_value_set_ulong (gvalue, *(gulong*)value);
+  case G_TYPE_ULONG:
+      g_value_set_ulong (gvalue, (gulong)value->rv_ffi_arg);
       break;
-    case G_TYPE_INT64:
-      g_value_set_int64 (gvalue, *(gint64*)value);
+  case G_TYPE_INT64:
+      g_value_set_int64 (gvalue, (gint64)value->rv_s64);
       break;
-    case G_TYPE_UINT64:
-      g_value_set_uint64 (gvalue, *(guint64*)value);
+  case G_TYPE_UINT64:
+      g_value_set_uint64 (gvalue, (guint64)value->rv_u64);
       break;
-    case G_TYPE_BOXED:
-      g_value_set_boxed (gvalue, *(gpointer*)value);
+  case G_TYPE_BOXED:
+      g_value_set_boxed (gvalue, (gpointer)value->rv_ffi_sarg);
       break;
-    default:
-      g_warning ("Unsupported fundamental type: %s",
-                g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))));
-    }
+  default:
+    g_warning ("Unsupported fundamental type: %s",
+	       g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))));
+  }
+
 }
 
 void
@@ -148,6 +225,7 @@ gi_cclosure_marshal_generic (GClosure *c
                              gpointer invocation_hint,
                              gpointer marshal_data)
 {
+  union FFIReturnValue return_ffi_value;
   ffi_type *rtype;
   void *rvalue;
   int n_args;
@@ -159,15 +237,16 @@ gi_cclosure_marshal_generic (GClosure *c
 
   if (return_gvalue && G_VALUE_TYPE (return_gvalue))
     {
+      rtype = g_value_to_ffi_return_type (return_gvalue, &return_ffi_value,
+					  &rvalue);
       rtype = value_to_ffi_type (return_gvalue, &rvalue);
     }
   else
     {
       rtype = &ffi_type_void;
+      rvalue = &return_ffi_value.rv_ffi_arg;
     }
 
-  rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
-
   n_args = n_param_values + 1;
   atypes = g_alloca (sizeof (ffi_type *) * n_args);
   args =  g_alloca (sizeof (gpointer) * n_args);
@@ -203,5 +282,5 @@ gi_cclosure_marshal_generic (GClosure *c
   ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
 
   if (return_gvalue && G_VALUE_TYPE (return_gvalue))
-    value_from_ffi_type (return_gvalue, rvalue);
+    g_value_from_ffi_value (return_gvalue, &return_ffi_value);
 }
