diff --git a/configure.ac b/configure.ac
index b5f009d..f3def76 100644
--- a/configure.ac
+++ b/configure.ac
@@ -107,9 +107,9 @@ GOBJECT_INTROSPECTION_LIBDIR="$EXPANDED_LIBDIR"
 AC_SUBST(GOBJECT_INTROSPECTION_LIBDIR)
 AC_DEFINE_UNQUOTED(GOBJECT_INTROSPECTION_LIBDIR,"$GOBJECT_INTROSPECTION_LIBDIR", [Directory prefix for typelib installation])
 
-PKG_CHECK_MODULES(GOBJECT, [gobject-2.0])
+PKG_CHECK_MODULES(GOBJECT, [gobject-2.0 gio-2.0])
 
-PKG_CHECK_MODULES(SCANNER, [gobject-2.0 gthread-2.0])
+PKG_CHECK_MODULES(SCANNER, [gobject-2.0 gthread-2.0 gio-2.0])
 
 dnl libffi
 PKG_CHECK_MODULES(FFI, libffi, have_ffi_pkgconfig=yes, have_ffi_pkgconfig=no)
@@ -147,7 +147,7 @@ if test x"$have_ffi_pkgconfig" = xno ; then
   AC_SUBST(FFI_CFLAGS)
 fi
 
-PKG_CHECK_MODULES(GIREPO, [glib-2.0 gobject-2.0 gmodule-2.0])
+PKG_CHECK_MODULES(GIREPO, [glib-2.0 gobject-2.0 gmodule-2.0 gio-2.0])
 
 # if we ever remove manual check for ffi and require .pc file, then 
 # just put libffi in the PKG_CHECK_MODULES(GIREPO) deps
diff --git a/gir/Makefile.am b/gir/Makefile.am
index 437adbf..11a37e6 100644
--- a/gir/Makefile.am
+++ b/gir/Makefile.am
@@ -21,6 +21,8 @@ GLib-2.0.gir: $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) Makefile glib-2.0.c
 	    -v --namespace GLib --nsversion=2.0 \
 	    --add-include-path=. \
 	    --noclosure \
+	    --uninstalled-introspection-srcdir=$(top_srcdir) \
+	    --uninstalled-introspection-builddir=$(top_builddir) \
 	    --output $@ \
 	    --strip-prefix=g \
 	    --library=$(GLIB_LIBRARY) \
@@ -52,6 +54,8 @@ GObject-2.0.gir: GLib-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) Makefile
 	    -v --namespace GObject --nsversion=2.0 \
 	    --add-include-path=. \
 	    --noclosure \
+	    --uninstalled-introspection-srcdir=$(top_srcdir) \
+	    --uninstalled-introspection-builddir=$(top_builddir) \
 	    --output $@ \
 	    --strip-prefix=g \
             --include=GLib-2.0 \
@@ -78,6 +82,8 @@ GModule-2.0.gir: GLib-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES)
 	    -v --namespace GModule --nsversion=2.0 \
 	    --add-include-path=. \
 	    --noclosure \
+	    --uninstalled-introspection-srcdir=$(top_srcdir) \
+	    --uninstalled-introspection-builddir=$(top_builddir) \
 	    --output $@ \
 	    --strip-prefix=g \
             --include=GLib-2.0 \
@@ -103,6 +109,8 @@ Gio-2.0.gir: GObject-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) Makefile $(sr
 	    -v --namespace Gio --nsversion=2.0 \
 	    --add-include-path=. \
 	    --noclosure \
+	    --uninstalled-introspection-srcdir=$(top_srcdir) \
+	    --uninstalled-introspection-builddir=$(top_builddir) \
 	    --output $@ \
 	    --strip-prefix=g \
             --include=GObject-2.0 \
diff --git a/girepository/Makefile.am b/girepository/Makefile.am
index be2d0d9..f0a312c 100644
--- a/girepository/Makefile.am
+++ b/girepository/Makefile.am
@@ -13,6 +13,7 @@ libgirepository_la_SOURCES =			\
 	gtypelib.h				\
 	gtypelib.c				\
 	ginfo.c					\
+	gdump.c					\
 	ginvoke.c
 libgirepository_la_CPPFLAGS = $(GIREPO_CFLAGS)
 libgirepository_la_LIBADD = $(GIREPO_LIBS)
diff --git a/girepository/gdump.c b/girepository/gdump.c
new file mode 100644
index 0000000..0f0d500
--- /dev/null
+++ b/girepository/gdump.c
@@ -0,0 +1,395 @@
+/* GObject introspection: Dump introspection data
+ *
+ * Copyright (C) 2008 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "girepository.h"
+#include "config.h"
+
+#include <string.h>
+
+static void
+goutput_printf (GOutputStream *out, const char *fmt, ...)
+{
+  char *str;
+  va_list args;
+  gsize written;
+  GError *error = NULL;
+
+  va_start (args, fmt);
+
+  str = g_strdup_vprintf (fmt, args);
+  if (!g_output_stream_write_all (out, str, strlen (str), &written, NULL, &error))
+    {
+      g_critical ("failed to write to iochannel: %s", error->message);
+      g_clear_error (&error);
+    }
+  g_free (str);
+
+  va_end (args);
+}
+
+static void
+goutput_write (GOutputStream *out, const char *buf)
+{
+  goutput_printf (out, "%s", buf);
+}
+
+typedef GType (*GetTypeFunc)(void);
+
+static GType
+invoke_get_type (GModule *self, const char *symbol)
+{
+  GetTypeFunc sym;
+
+  if (!g_module_symbol (self, symbol, (void**)&sym))
+    {
+      g_critical ("Failed to find symbol '%s'", symbol);
+      return G_TYPE_INVALID;
+    }
+
+  return sym ();
+}
+
+static void
+dump_properties (GType type, GOutputStream *out)
+{
+  guint i;
+  guint n_properties;
+  GParamSpec **props;
+
+  if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_OBJECT)
+    {
+      GObjectClass *klass;
+      klass = g_type_class_ref (type);
+      props = g_object_class_list_properties (klass, &n_properties);
+    }
+  else
+    {
+      void *klass;
+      klass = g_type_default_interface_ref (type);
+      props = g_object_interface_list_properties (klass, &n_properties);
+    }
+
+  for (i = 0; i < n_properties; i++)
+    {
+      GParamSpec *prop;
+      char *name;
+      char *value_name;
+
+      prop = props[i];
+      if (prop->owner_type != type)
+	continue;
+
+      name = g_markup_escape_text (prop->name, -1);
+      value_name = g_markup_escape_text (g_type_name (prop->value_type), -1);
+      goutput_printf (out, "    <property name=\"%s\" type=\"%s\" flags=\"%d\"/>\n",
+			name, value_name, prop->flags);
+      g_free (name);
+      g_free (value_name);
+    }
+  g_free (props);
+}
+
+static void
+dump_signals (GType type, GOutputStream *out)
+{
+  guint i;
+  guint n_sigs;
+  guint *sig_ids;
+
+  sig_ids = g_signal_list_ids (type, &n_sigs);
+  for (i = 0; i < n_sigs; i++)
+    {
+      guint sigid;
+      GSignalQuery query;
+      char *name;
+      char *return_name;
+      guint j;
+
+      sigid = sig_ids[i];
+      g_signal_query (sigid, &query);
+
+      name = g_markup_escape_text (query.signal_name, -1);
+      return_name = g_markup_escape_text (g_type_name (query.return_type), -1);
+      goutput_printf (out, "    <signal name=\"%s\" return=\"%s\">\n",
+		      name, return_name);
+      g_free (name);
+      g_free (return_name);
+
+      for (j = 0; j < query.n_params; j++)
+	{
+	  char *type;
+	  type = g_markup_escape_text (g_type_name (query.param_types[j]), -1);
+	  goutput_printf (out, "      <param type=\"%s\"/>\n", type);
+	  g_free (type);
+	}
+      goutput_write (out, "    </signal>\n");
+    }
+}
+
+static void
+dump_object_type (GType type, const char *symbol, GOutputStream *out)
+{
+  char *name;
+  guint n_interfaces;
+  guint i;
+  GType *interfaces;
+
+  name = g_markup_escape_text (g_type_name (type), -1);
+  goutput_printf (out, "  <class name=\"%s\" get-type=\"%s\"",
+		  name, symbol);
+  if (type != G_TYPE_OBJECT)
+    {
+      char *parent = g_markup_escape_text (g_type_name (g_type_parent (type)), -1);
+      goutput_printf (out, " parent=\"%s\"", parent);
+      g_free (parent);
+    }
+  if (G_TYPE_IS_ABSTRACT (type))
+    goutput_write (out, " abstract=\"1\"");
+  goutput_write (out, ">\n");
+  g_free (name);
+
+  interfaces = g_type_interfaces (type, &n_interfaces);
+  for (i = 0; i < n_interfaces; i++)
+    {
+      GType itype = interfaces[i];
+      name = g_markup_escape_text (g_type_name (itype), -1);
+      goutput_printf (out, "    <implements name=\"%s\"/>\n", name);
+      g_free (name);
+    }
+  dump_properties (type, out);
+  dump_signals (type, out);
+  goutput_write (out, "  </class>\n");
+}
+
+static void
+dump_interface_type (GType type, const char *symbol, GOutputStream *out)
+{
+  char *name;
+  char *parent;
+  guint n_interfaces;
+  guint i;
+  GType *interfaces;
+
+  name = g_markup_escape_text (g_type_name (type), -1);
+  parent = g_markup_escape_text (g_type_name (g_type_parent (type)), -1);
+  goutput_printf (out, "  <interface name=\"%s\" parent=\"%s\" get-type=\"%s\">\n",
+		  name, parent, symbol);
+  g_free (name);
+  g_free (parent);
+
+  interfaces = g_type_interface_prerequisites (type, &n_interfaces);
+  for (i = 0; i < n_interfaces; i++)
+    {
+      GType itype = interfaces[i];
+      name = g_markup_escape_text (g_type_name (itype), -1);
+      goutput_printf (out, "    <extends>%s</extends>\n", name);
+      g_free (name);
+    }
+  dump_properties (type, out);
+  dump_signals (type, out);
+  goutput_write (out, "  </interface>\n");
+}
+
+static void
+dump_boxed_type (GType type, const char *symbol, GOutputStream *out)
+{
+  char *name;
+
+  name = g_markup_escape_text (g_type_name (type), -1);
+  goutput_printf (out, "  <boxed name=\"%s\" get-type=\"%s\"/>\n",
+		  name, symbol);
+  g_free (name);
+}
+
+static void
+dump_flags_type (GType type, const char *symbol, GOutputStream *out)
+{
+  char *name;
+  guint i;
+  GFlagsClass *klass;
+
+  klass = g_type_class_ref (type);
+  name = g_markup_escape_text (g_type_name (type), -1);
+  goutput_printf (out, "  <flags name=\"%s\" get-type=\"%s\">\n",
+		  name, symbol);
+  g_free (name);
+
+  for (i = 0; i < klass->n_values; i++)
+    {
+      char *nick;
+      GFlagsValue *value = &(klass->values[i]);
+
+      name = g_markup_escape_text (value->value_name, -1);
+      nick = g_markup_escape_text (value->value_nick, -1);
+      goutput_printf (out, "    <member name=\"%s\" nick=\"%s\" value=\"%d\"/>\n",
+		      name, nick, value->value);
+      g_free (name);
+      g_free (nick);
+    }
+  goutput_write (out, "  </flags>\n");
+}
+
+static void
+dump_enum_type (GType type, const char *symbol, GOutputStream *out)
+{
+  char *name;
+  guint i;
+  GEnumClass *klass;
+
+  klass = g_type_class_ref (type);
+  name = g_markup_escape_text (g_type_name (type), -1);
+  goutput_printf (out, "  <enum name=\"%s\" get-type=\"%s\">\n",
+		  name, symbol);
+  g_free (name);
+
+  for (i = 0; i < klass->n_values; i++)
+    {
+      char *nick;
+      GEnumValue *value = &(klass->values[i]);
+
+      name = g_markup_escape_text (value->value_name, -1);
+      nick = g_markup_escape_text (value->value_nick, -1);
+      goutput_printf (out, "    <member name=\"%s\" nick=\"%s\" value=\"%d\"/>\n",
+		      name, nick, value->value);
+      g_free (name);
+      g_free (nick);
+    }
+  goutput_write (out, "  </enum>");
+}
+
+static void
+dump_type (GType type, const char *symbol, GOutputStream *out)
+{
+  g_printerr ("processing %s\n", g_type_name (type));
+  switch (g_type_fundamental (type))
+    {
+    case G_TYPE_OBJECT:
+      dump_object_type (type, symbol, out);
+      break;
+    case G_TYPE_INTERFACE:
+      dump_interface_type (type, symbol, out);
+      break;
+    case G_TYPE_BOXED:
+      dump_boxed_type (type, symbol, out);
+      break;
+    case G_TYPE_FLAGS:
+      dump_flags_type (type, symbol, out);
+      break;
+    case G_TYPE_ENUM:
+      dump_enum_type (type, symbol, out);
+      break;
+    case G_TYPE_POINTER:
+      /* GValue, etc.  Just skip them. */
+      break;
+    default:
+      g_warning ("unhandled gtype %s", g_type_name (type));
+    }
+}
+
+/**
+ * g_irepository_dump:
+ * @arg: Comma-separated pair of input and output filenames
+ *
+ * Outputs introspection information for each 
+ *
+ * Returns: %TRUE if the function has been invoked, %FALSE if an
+ *   error occurred. 
+ */
+void
+g_irepository_dump (const char *arg)
+{
+  GHashTable *output_types;
+  char **args;
+  GFile *input_file;
+  GFile *output_file;
+  GFileInputStream *input;
+  GFileOutputStream *output;
+  GDataInputStream *in;
+  GError *error = NULL;
+  GModule *self;
+
+  self = g_module_open (NULL, 0);
+
+  args = g_strsplit (arg, ",", 2);
+
+  input_file = g_file_new_for_path (args[0]);
+  output_file = g_file_new_for_path (args[1]);
+
+  input = g_file_read (input_file, NULL, &error);
+  if (input == NULL)
+    {
+      g_critical ("Failed to read input file '%s': %s'", args[0],
+		  error->message);
+      g_clear_error (&error);
+      return;
+    }
+  output = g_file_replace (output_file, NULL, FALSE, 0, NULL, &error);
+  if (output == NULL)
+    {
+      g_critical ("Failed to replace (for output) file '%s': %s'", args[1],
+		  error->message);
+      g_clear_error (&error);
+      return;
+    }
+
+  goutput_write (G_OUTPUT_STREAM (output), "<?xml version=\"1.0\"?>\n");
+  goutput_write (G_OUTPUT_STREAM (output), "<dump>\n");
+
+  output_types = g_hash_table_new (NULL, NULL);
+
+  in = g_data_input_stream_new (G_INPUT_STREAM (input));
+  g_object_unref (input);
+
+  while (TRUE)
+    {
+      gsize len;
+      char *line = g_data_input_stream_read_line (in, &len, NULL, NULL);
+      GType type;
+      if (line == NULL || *line == '\0')
+	{
+	  g_free (line);
+	  break;
+	}
+
+      g_strchomp (line);
+      type = invoke_get_type (self, line);
+
+      if (g_hash_table_lookup (output_types, (gpointer) type))
+	continue;
+      g_hash_table_insert (output_types, (gpointer) type, (gpointer) type);
+
+      dump_type (type, line, G_OUTPUT_STREAM (output));
+
+      g_free (line);
+    }
+
+  g_hash_table_destroy (output_types);
+
+  goutput_write (G_OUTPUT_STREAM (output), "</dump>\n");
+
+  g_input_stream_close (G_INPUT_STREAM (in), NULL, NULL);
+  g_output_stream_close (G_OUTPUT_STREAM (output), NULL, NULL);
+}
diff --git a/girepository/girepository.h b/girepository/girepository.h
index c40b6b7..30b97c3 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -109,6 +109,8 @@ const gchar * g_irepository_get_shared_library (GIRepository *repository,
 const gchar * g_irepository_get_version (GIRepository *repository,
 					 const gchar  *namespace);
 
+void          g_irepository_dump (const char *arg);
+
 /* Typelib */
 
 GTypelib *   g_typelib_new_from_memory       (guchar       *memory,
diff --git a/giscanner/Makefile.am b/giscanner/Makefile.am
index c9d23e5..9de1eb6 100644
--- a/giscanner/Makefile.am
+++ b/giscanner/Makefile.am
@@ -37,7 +37,6 @@ pkgpyexec_PYTHON = 		\
 	__init__.py		\
 	ast.py			\
 	cachestore.py		\
-	cgobject.py		\
 	config.py		\
 	girparser.py		\
 	girwriter.py		\
diff --git a/giscanner/cgobject.py b/giscanner/cgobject.py
deleted file mode 100644
index 308ebf4..0000000
--- a/giscanner/cgobject.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# -*- Mode: Python -*-
-# GObject-Introspection - a framework for introspecting GObject libraries
-# Copyright (C) 2008  Johan Dahlin
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
-# Poor mans GObject python bindings
-# Incidentally portable beyond CPython, due to usage of ctypes
-# Why not PyGObject?
-# - 1) Avoid PyGObject dependency
-# - 2) Low-level binding
-# - 3) Implementation independent
-# - 4) Usage lower in the stack
-#
-# based on defsgen.py (C) 2006 John Finlay
-#
-
-import os
-import ctypes
-from ctypes.util import find_library
-
-
-# Constants
-
-# from gobject/gtype.h
-
-
-def _make_fundamental(x):
-    G_TYPE_FUNDAMENTAL_SHIFT = 2
-    return x << G_TYPE_FUNDAMENTAL_SHIFT
-
-
-TYPE_INVALID = _make_fundamental(0)
-TYPE_NONE = _make_fundamental(1)
-TYPE_INTERFACE = _make_fundamental(2)
-TYPE_CHAR = _make_fundamental(3)
-TYPE_UCHAR = _make_fundamental(4)
-TYPE_BOOLEAN = _make_fundamental(5)
-TYPE_INT = _make_fundamental(6)
-TYPE_UINT = _make_fundamental(7)
-TYPE_LONG = _make_fundamental(8)
-TYPE_ULONG = _make_fundamental(9)
-TYPE_INT64 = _make_fundamental(10)
-TYPE_UINT64 = _make_fundamental(11)
-TYPE_ENUM = _make_fundamental(12)
-TYPE_FLAGS = _make_fundamental(13)
-TYPE_FLOAT = _make_fundamental(14)
-TYPE_DOUBLE = _make_fundamental(15)
-TYPE_STRING = _make_fundamental(16)
-TYPE_POINTER = _make_fundamental(17)
-TYPE_BOXED = _make_fundamental(18)
-TYPE_PARAM = _make_fundamental(19)
-TYPE_OBJECT = _make_fundamental(20)
-
-# Typedefs
-
-# FIXME - this is wrong on win64, where long == 32 but size_t == 64
-GType = ctypes.c_ulong
-
-TYPE_FLAG_ABSTRACT = 1 << 4
-
-# Structs
-
-
-class GTypeClass(ctypes.Structure):
-    _fields_ = [('g_type', GType)]
-
-
-class GTypeInstance(ctypes.Structure):
-    _fields_ = [('g_class', ctypes.POINTER(GTypeClass))]
-
-
-class GEnumValue(ctypes.Structure):
-    _fields_ = [('value', ctypes.c_int),
-                ('value_name', ctypes.c_char_p),
-                ('value_nick', ctypes.c_char_p)]
-
-
-class GFlagsValue(ctypes.Structure):
-    _fields_ = [('value', ctypes.c_uint),
-                ('value_name', ctypes.c_char_p),
-                ('value_nick', ctypes.c_char_p)]
-
-
-class GEnumClass(ctypes.Structure):
-    _fields_ = [('g_type_class', GTypeClass),
-                ('minimum', ctypes.c_int),
-                ('maximum', ctypes.c_int),
-                ('n_values', ctypes.c_uint),
-                ('values', ctypes.POINTER(GEnumValue))]
-
-    def get_values(self):
-        for i in range(self.n_values):
-            yield self.values[i]
-
-
-class GFlagsClass(ctypes.Structure):
-    _fields_ = [('g_type_class', GTypeClass),
-               ('mask', ctypes.c_uint),
-               ('n_values', ctypes.c_uint),
-               ('values', ctypes.POINTER(GFlagsValue))]
-
-    def get_values(self):
-        for i in range(self.n_values):
-            yield self.values[i]
-
-
-class GTypeInterface(ctypes.Structure):
-    _fields_ = [('g_type', GType),
-                ('g_instance_type', GType)]
-
-
-class GParamSpec(ctypes.Structure):
-    _fields_ = [('g_type_instance', GTypeInstance),
-                ('name', ctypes.c_char_p),
-                ('flags', ctypes.c_uint),
-                ('value_type', GType),
-                ('owner_type', GType)]
-
-
-class GSignalInfo(ctypes.Structure):
-    _fields_ = [('signal_id', ctypes.c_uint),
-                ('signal_name', ctypes.c_char_p),
-                ('itype', GType),
-                ('signal_flags', ctypes.c_uint),
-                ('return_type', GType),
-                ('n_params', ctypes.c_uint),
-                ('param_types', ctypes.POINTER(GType))]
-
-    def get_params(self):
-        for i in range(self.n_params):
-            yield self.param_types[i]
-
-
-if os.name == 'nt':
-    _library_path = find_library('libgobject-2.0-0')
-else:
-    _library_path = find_library('gobject-2.0')
-if not _library_path:
-    raise ImportError("Could not find gobject-2.0 library")
-_gobj = ctypes.CDLL(_library_path, ctypes.RTLD_GLOBAL)
-_gobj.g_type_init()
-
-# We need to initialize threads just in case part of the library
-# wants to use gthreads; libsoup seems to use g_once for its
-# type init functions.
-if os.name == 'nt':
-    _threads_library_path = find_library('libgthread-2.0-0')
-else:
-    _threads_library_path = find_library('gthread-2.0')
-if not _threads_library_path:
-    raise ImportError("Could not find gthread-2.0 library")
-_gthreads = ctypes.CDLL(_threads_library_path, ctypes.RTLD_GLOBAL)
-_gthreads.g_thread_init.argtypes = [ctypes.c_void_p]
-_gthreads.g_thread_init(None)
-
-# Functions
-
-
-def _gwrap(fname, ret, *argtypes):
-
-    def _deco(f):
-        f._cfunc = getattr(_gobj, fname)
-        f._cfunc.restype = ret
-        f._cfunc.argtypes = argtypes
-        return f
-    return _deco
-
-
-@_gwrap('g_object_new', ctypes.c_void_p, GType)
-def object_new(type_id):
-    return _gobj.g_object_new(type_id, None)
-
-
-# Workaround this error:
-#   GLib-GObject-CRITICAL **: g_param_spec_pool_list:
-#   assertion `pool != NULL' failed
-# which happens when trying to introspect an interface before instantiating
-# a GObject.
-
-object_new(TYPE_OBJECT)
-_gobj.g_initially_unowned_get_type()
-
-
-@_gwrap('g_type_name', ctypes.c_char_p, GType)
-def type_name(type_id):
-    return _gobj.g_type_name(type_id)
-
-
-@_gwrap('g_type_from_name', GType, ctypes.c_char_p)
-def type_from_name(name):
-    return _gobj.g_type_from_name(name)
-
-
-@_gwrap('g_type_fundamental', GType, GType)
-def type_fundamental(type_id):
-    return _gobj.g_type_fundamental(type_id)
-
-
-@_gwrap('g_type_test_flags', ctypes.c_int, GType, ctypes.c_int)
-def type_test_flags(type_id, flag):
-    return _gobj.g_type_test_flags(type_id, flag)
-
-
-def type_is_abstract(type_id):
-    return type_test_flags(type_id, TYPE_FLAG_ABSTRACT) != 0
-
-
-@_gwrap('g_type_parent', GType, GType)
-def type_parent(type_id):
-    return _gobj.g_type_parent(type_id)
-
-
-@_gwrap('g_type_class_ref', ctypes.POINTER(GTypeClass), GType)
-def type_class_ref(type_id):
-    fundamental_type = type_fundamental(type_id)
-    if fundamental_type == TYPE_INVALID:
-        return None
-    if fundamental_type == TYPE_ENUM:
-        typeclass = GEnumClass
-    elif fundamental_type == TYPE_FLAGS:
-        typeclass = GFlagsClass
-    else:
-        raise NotImplementedError(fundamental_type)
-    ptr = _gobj.g_type_class_ref(type_id)
-    return ctypes.cast(ptr, ctypes.POINTER(typeclass)).contents
-
-
-@_gwrap('g_object_class_list_properties',
-       ctypes.POINTER(ctypes.POINTER(GParamSpec)),
-       ctypes.POINTER(GTypeClass), ctypes.POINTER(ctypes.c_uint))
-def object_class_list_properties(type_id):
-    klass = _gobj.g_type_class_ref(type_id)
-    n = ctypes.c_uint()
-    pspecs = _gobj.g_object_class_list_properties(klass, ctypes.byref(n))
-    for i in range(n.value):
-        yield ctypes.cast(pspecs[i], ctypes.POINTER(GParamSpec)).contents
-
-
-@_gwrap('g_type_default_interface_ref', ctypes.c_void_p, GType)
-def type_default_interface_ref(type_id):
-    return _gobj.g_type_default_interface_ref(type_id)
-
-
-@_gwrap('g_object_interface_list_properties',
-       ctypes.POINTER(ctypes.POINTER(GParamSpec)),
-       ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint))
-def object_interface_list_properties(type_id):
-    iface = type_default_interface_ref(type_id)
-    n = ctypes.c_uint()
-    pspecs = _gobj.g_object_interface_list_properties(iface, ctypes.byref(n))
-    for i in range(n.value):
-        yield ctypes.cast(pspecs[i], ctypes.POINTER(GParamSpec)).contents
-
-
-@_gwrap('g_type_interfaces', ctypes.POINTER(GType), GType,
-       ctypes.POINTER(ctypes.c_uint))
-def type_interfaces(type_id):
-    n = ctypes.c_uint()
-    type_ids = _gobj.g_type_interfaces(type_id, ctypes.byref(n))
-    for i in range(n.value):
-        yield type_ids[i]
-
-
-@_gwrap('g_type_interface_prerequisites', ctypes.POINTER(GType), GType,
-       ctypes.POINTER(ctypes.c_uint))
-def type_interface_prerequisites(type_id):
-    n = ctypes.c_uint()
-    type_ids = _gobj.g_type_interface_prerequisites(type_id, ctypes.byref(n))
-    for i in range(n.value):
-        yield type_ids[i]
-
-
-@_gwrap('g_signal_query', None, ctypes.c_uint, ctypes.POINTER(GSignalInfo))
-def signal_query(sigid, qptr):
-    _gobj.g_signal_query(sigid, qptr)
-
-
-@_gwrap('g_signal_list_ids', ctypes.POINTER(ctypes.c_uint),
-       GType, ctypes.POINTER(ctypes.c_uint))
-def signal_list(type_id):
-    n = ctypes.c_uint()
-    signal_ids = _gobj.g_signal_list_ids(type_id, ctypes.byref(n))
-    for i in range(n.value):
-        info = GSignalInfo()
-        signal_query(signal_ids[i], ctypes.byref(info))
-        yield info
-
-TYPE_GTYPE = type_from_name('GType')
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 09fcb8d..005ffdd 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -19,11 +19,11 @@
 #
 
 import os
+import sys
 import re
-import ctypes
-from ctypes.util import find_library
+import tempfile
+import subprocess
 
-from . import cgobject
 from .ast import (Callback, Constant, Enum, Function, Member, Namespace,
                   Parameter, Property, Return, Struct, Type, Alias,
                   Union, Field, type_name_from_ctype,
@@ -32,7 +32,7 @@ from .transformer import Names
 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
                       GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
                       GLibBoxedUnion, GLibBoxedOther, type_names)
-from .utils import extract_libtool, to_underscores, to_underscores_noprefix
+from .utils import to_underscores, to_underscores_noprefix
 
 default_array_types['guchar*'] = TYPE_UINT8
 
@@ -68,7 +68,9 @@ class GLibTransformer(object):
         self._namespace_name = None
         self._names = Names()
         self._uscore_type_names = {}
-        self._libraries = []
+        self._binary = None
+        self._get_type_functions = []
+        self._gtype_data = {}
         self._failed_types = {}
         self._boxed_types = {}
         self._private_internal_types = {}
@@ -77,20 +79,8 @@ class GLibTransformer(object):
 
     # Public API
 
-    def add_library(self, libname):
-        # For testing mainly.
-        libtool_libname = 'lib' + libname + '.la'
-        if os.path.exists(libname):
-            found_libname = os.path.abspath(libname)
-        elif os.path.exists(libtool_libname):
-            found_libname = extract_libtool(libtool_libname)
-        elif libname.endswith('.la'):
-            found_libname = extract_libtool(libname)
-        else:
-            found_libname = find_library(libname)
-        if not found_libname:
-            raise ValueError("Failed to find library: %r" % (libname, ))
-        self._libraries.append(ctypes.cdll.LoadLibrary(found_libname))
+    def set_introspection_binary(self, binary):
+        self._binary = binary
 
     def _print_statistics(self):
         nodes = list(self._names.names.itervalues())
@@ -117,6 +107,11 @@ class GLibTransformer(object):
         if namespace.name == 'GObject':
             del self._names.aliases['Type']
 
+        # Get all the GObject data by passing our list of get_type
+        # functions to the compiled binary
+
+        self._execute_binary()
+
         # Introspection is done from within parsing
 
         # Second pass: pair boxed structures
@@ -166,6 +161,16 @@ class GLibTransformer(object):
             return node[1]
         return None
 
+    def _lookup_node(self, name):
+        if name in type_names:
+            return None
+        node = self._get_attribute(name)
+        if node is None:
+            node = self._transformer.get_names().names.get(name)
+            if node:
+                return node[1]
+        return node
+
     def _register_internal_type(self, type_name, node):
         self._names.type_names[type_name] = (None, node)
         uscored = to_underscores(type_name).lower()
@@ -180,16 +185,6 @@ class GLibTransformer(object):
 
     # Helper functions
 
-    def _type_from_gtype(self, type_id):
-        ctype = cgobject.type_name(type_id)
-        type_name = type_name_from_ctype(ctype)
-        type_name = type_name.replace('*', '')
-        type_name = self._resolve_type_name(type_name)
-
-        type = Type(type_name, ctype)
-        type._gtype = type_id
-        return type
-
     def _resolve_gtypename(self, gtype_name):
         try:
             return self._transformer.gtypename_to_giname(gtype_name,
@@ -197,21 +192,46 @@ class GLibTransformer(object):
         except KeyError, e:
             return Unresolved(gtype_name)
 
+    def _execute_binary(self):
+        (fd, in_path) = tempfile.mkstemp('.txt', 'tmp-introspect-types')
+        f = os.fdopen(fd, 'w')
+        for func in self._get_type_functions:
+            f.write(func)
+            f.write('\n')
+        f.close()
+        (fd, out_path) = tempfile.mkstemp('.xml', 'tmp-introspect-data')
+        os.close(fd)
+
+        introspect_arg = '--introspect=%s,%s' % (in_path, out_path)
+        real_bin = self._binary[0]
+        args = [real_bin, introspect_arg]
+        print args
+        subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
+        self._read_introspect_dump(out_path)
+        for fpath in self._binary:
+            os.unlink(fpath)
+        os.unlink(in_path)
+        os.unlink(out_path)
+
+    def _read_introspect_dump(self, xmlpath):
+        from xml.etree.cElementTree import parse
+        tree = parse(xmlpath)
+        root = tree.getroot()
+        for child in root:
+            self._gtype_data[child.attrib['name']] = child
+        for child in root:
+            self._introspect_type(child)
+
     def _create_gobject(self, node):
         type_name = 'G' + node.name
         if type_name == 'GObject':
             parent_gitype = None
             symbol = 'intern'
-        else:
-            type_id = cgobject.type_from_name(type_name)
-            parent_type_name = cgobject.type_name(
-                cgobject.type_parent(type_id))
+        elif type_name == 'GInitiallyUnowned':
+            parent_type_name = 'GObject'
             parent_gitype = self._resolve_gtypename(parent_type_name)
-            symbol = to_underscores(type_name).lower() + '_get_type'
+            symbol = 'g_initially_unowned_get_type'
         node = GLibObject(node.name, parent_gitype, type_name, symbol, True)
-        type_id = cgobject.TYPE_OBJECT
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
         self._add_attribute(node)
         self._register_internal_type(type_name, node)
 
@@ -278,26 +298,7 @@ class GLibTransformer(object):
         if func.parameters:
             return False
 
-        if not self._libraries:
-            print "Warning: No libraries loaded, cannot call %s" % (symbol, )
-            return False
-
-        for library in self._libraries:
-            try:
-                func = getattr(library, symbol)
-                break
-            except AttributeError:
-                continue
-        else:
-            print 'Warning: could not find symbol: %s' % symbol
-            name = symbol.replace('_get_type', '')
-            self._failed_types[name] = True
-            return False
-
-        func.restype = cgobject.GType
-        func.argtypes = []
-        type_id = func()
-        self._introspect_type(type_id, symbol)
+        self._get_type_functions.append(symbol)
         return True
 
     def _name_is_internal_gtype(self, giname):
@@ -488,65 +489,51 @@ class GLibTransformer(object):
 
     # Introspection
 
-    def _introspect_type(self, type_id, symbol):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if (fundamental_type_id == cgobject.TYPE_ENUM or
-            fundamental_type_id == cgobject.TYPE_FLAGS):
-            self._introspect_enum(fundamental_type_id, type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_OBJECT:
-            self._introspect_object(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_INTERFACE:
-            self._introspect_interface(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_BOXED:
-            self._introspect_boxed(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_BOXED:
-            self._introspect_boxed(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_POINTER:
-            # FIXME: Should we do something about these?
-            #        GHashTable, GValue and a few other fundamentals are
-            #        covered here
-            return
+    def _introspect_type(self, xmlnode):
+        if xmlnode.tag in ('enum', 'flags'):
+            self._introspect_enum(xmlnode)
+        elif xmlnode.tag == 'class':
+            self._introspect_object(xmlnode)
+        elif xmlnode.tag == 'interface':
+            self._introspect_interface(xmlnode)
+        elif xmlnode.tag == 'boxed':
+            self._introspect_boxed(xmlnode)
         else:
-            print 'unhandled GType: %s(%d)' % (cgobject.type_name(type_id),
-                                               type_id)
-
-    def _introspect_enum(self, ftype_id, type_id, symbol):
-        type_class = cgobject.type_class_ref(type_id)
-        if type_class is None:
-            return
+            raise ValueError("Unhandled introspection XML tag %s", xmlnode.tag)
 
+    def _introspect_enum(self, node):
         members = []
-        for enum_value in type_class.get_values():
-            members.append(GLibEnumMember(enum_value.value_nick,
-                                          enum_value.value,
-                                          enum_value.value_name,
-                                          enum_value.value_nick))
-
-        klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
-        type_name = cgobject.type_name(type_id)
+        for member in node.findall('member'):
+            members.append(GLibEnumMember(member.attrib['nick'],
+                                          member.attrib['value'],
+                                          member.attrib['name'],
+                                          member.attrib['nick']))
+
+        klass = (GLibFlags if node.tag == 'flags' else GLibEnum)
+        type_name = node.attrib['name']
         enum_name = self._transformer.remove_prefix(type_name)
-        node = klass(enum_name, type_name, members, symbol)
+        node = klass(enum_name, type_name, members, node.attrib['get-type'])
         self._add_attribute(node, replace=True)
         self._register_internal_type(type_name, node)
 
-    def _introspect_object(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
+    def _introspect_object(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         # We handle this specially above; in 2.16 and below there
         # was no g_object_get_type, for later versions we need
         # to skip it
         if type_name == 'GObject':
             return
-        parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
+        parent_type_name = xmlnode.attrib['parent']
         parent_gitype = self._resolve_gtypename(parent_type_name)
-        is_abstract = cgobject.type_is_abstract(type_id)
+        is_abstract = not not xmlnode.attrib.get('abstract', False)
         node = GLibObject(
             self._transformer.remove_prefix(type_name),
             parent_gitype,
             type_name,
-            symbol, is_abstract)
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
-        self._introspect_implemented_interfaces(node, type_id)
+            xmlnode.attrib['get-type'], is_abstract)
+        self._introspect_properties(node, xmlnode)
+        self._introspect_signals(node, xmlnode)
+        self._introspect_implemented_interfaces(node, xmlnode)
 
         # add struct fields
         struct = self._get_attribute(node.name)
@@ -561,9 +548,9 @@ class GLibTransformer(object):
         self._add_attribute(node, replace=True)
         self._register_internal_type(type_name, node)
 
-    def _introspect_interface(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
-        parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
+    def _introspect_interface(self, xmlnode):
+        type_name = xmlnode.attrib['name']
+        parent_type_name = xmlnode.attrib['parent']
         if parent_type_name == 'GInterface':
             parent_gitype = None
         else:
@@ -571,74 +558,64 @@ class GLibTransformer(object):
         node = GLibInterface(
             self._transformer.remove_prefix(type_name),
             parent_gitype,
-            type_name, symbol)
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
+            type_name, xmlnode.attrib['get-type'])
+        self._introspect_properties(node, xmlnode)
+        self._introspect_signals(node, xmlnode)
         # GtkFileChooserEmbed is an example of a private interface, we
         # just filter them out
-        if symbol.startswith('_'):
+        if xmlnode.attrib['get-type'].startswith('_'):
             print "NOTICE: Marking %s as internal type" % (type_name, )
             self._private_internal_types[type_name] = node
         else:
             self._add_attribute(node, replace=True)
             self._register_internal_type(type_name, node)
 
-    def _introspect_boxed(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
+    def _introspect_boxed(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         # This one doesn't go in the main namespace; we associate it with
         # the struct or union
-        node = GLibBoxed(type_name, symbol)
+        node = GLibBoxed(type_name, xmlnode.attrib['get-type'])
         self._boxed_types[node.type_name] = node
         self._register_internal_type(type_name, node)
 
-    def _introspect_implemented_interfaces(self, node, type_id):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if fundamental_type_id != cgobject.TYPE_OBJECT:
-            raise AssertionError
-        interfaces = cgobject.type_interfaces(type_id)
+    def _introspect_implemented_interfaces(self, node, xmlnode):
         gt_interfaces = []
-        for interface_typeid in interfaces:
-            iname = cgobject.type_name(interface_typeid)
-            gitype = self._resolve_gtypename(iname)
+        for interface in xmlnode.findall('implements'):
+            gitype = self._resolve_gtypename(interface.attrib['name'])
             gt_interfaces.append(gitype)
         node.interfaces = gt_interfaces
 
-    def _introspect_properties(self, node, type_id):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if fundamental_type_id == cgobject.TYPE_OBJECT:
-            pspecs = cgobject.object_class_list_properties(type_id)
-        elif fundamental_type_id == cgobject.TYPE_INTERFACE:
-            pspecs = cgobject.object_interface_list_properties(type_id)
-        else:
-            raise AssertionError
-
-        for pspec in pspecs:
-            if pspec.owner_type != type_id:
-                continue
-            ctype = cgobject.type_name(pspec.value_type)
-            readable = (pspec.flags & 1) != 0
-            writable = (pspec.flags & 2) != 0
-            construct = (pspec.flags & 4) != 0
-            construct_only = (pspec.flags & 8) != 0
+    def _introspect_properties(self, node, xmlnode):
+        for pspec in xmlnode.findall('property'):
+            ctype = pspec.attrib['type']
+            flags = int(pspec.attrib['flags'])
+            readable = (flags & 1) != 0
+            writable = (flags & 2) != 0
+            construct = (flags & 4) != 0
+            construct_only = (flags & 8) != 0
             node.properties.append(Property(
-                pspec.name,
+                pspec.attrib['name'],
                 type_name_from_ctype(ctype),
                 readable, writable, construct, construct_only,
                 ctype,
                 ))
 
-    def _introspect_signals(self, node, type_id):
-        for signal_info in cgobject.signal_list(type_id):
-            rtype = self._type_from_gtype(signal_info.return_type)
-            return_ = Return(rtype)
-            signal = GLibSignal(signal_info.signal_name, return_)
-            for i, parameter in enumerate(signal_info.get_params()):
+    def _introspect_signals(self, node, xmlnode):
+        for signal_info in xmlnode.findall('signal'):
+            rctype = signal_info.attrib['return']
+            rtype = Type(self._transformer.parse_ctype(rctype), rctype)
+            return_ = Return(rtype, signal_info.attrib['return'])
+            return_.transfer = 'full'
+            signal = GLibSignal(signal_info.attrib['name'], return_)
+            for i, parameter in enumerate(signal_info.findall('param')):
                 if i == 0:
                     name = 'object'
                 else:
                     name = 'p%s' % (i-1, )
-                ptype = self._type_from_gtype(parameter)
+                pctype = parameter.attrib['type']
+                ptype = Type(self._transformer.parse_ctype(pctype), pctype)
                 param = Parameter(name, ptype)
+                param.transfer = 'none'
                 signal.parameters.append(param)
             node.signals.append(signal)
 
@@ -648,7 +625,6 @@ class GLibTransformer(object):
         # Workaround glib bug #548689, to be included in 2.18.0
         if type_name == "GParam":
             type_name = "GObject.ParamSpec"
-
         res = self._transformer.resolve_type_name_full
         try:
             return res(type_name, ctype, self._names)
@@ -656,6 +632,9 @@ class GLibTransformer(object):
             return self._transformer.resolve_type_name(type_name, ctype)
 
     def _resolve_param_type(self, ptype, **kwargs):
+        # Workaround glib bug #548689, to be included in 2.18.0
+        if ptype.name == "GParam":
+            ptype.name = "GObject.ParamSpec"
         return self._transformer.resolve_param_type_full(ptype,
                                                          self._names,
                                                          **kwargs)
@@ -780,43 +759,23 @@ class GLibTransformer(object):
         prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
 
     def _adjust_transfer(self, param):
-        # Do GLib/GObject-specific type transformations here
-
-        transfer = None
-        is_object = None
-        if hasattr(param.type, '_gtype'):
-            ftype = cgobject.type_fundamental(param.type._gtype)
-            assert ftype != cgobject.TYPE_INVALID, param.type._gtype
+        if not (param.transfer is None or param.transfer_inferred):
+            return
 
-            is_object = ftype in [cgobject.TYPE_OBJECT,
-                                  cgobject.TYPE_INTERFACE]
+        # Do GLib/GObject-specific type transformations here
+        node = self._lookup_node(param.type.name)
+        if node is None:
+            return
 
-            if ftype in [cgobject.TYPE_OBJECT,
-                         cgobject.TYPE_INTERFACE,
-                         cgobject.TYPE_STRING,
-                         cgobject.TYPE_BOXED,
-                         cgobject.TYPE_PARAM]:
+        if isinstance(param, Parameter):
+            if param.direction != PARAM_DIRECTION_IN:
                 transfer = 'full'
             else:
-                # if type is a cgobject.TYPE_POINTER we could require direction
-                # and transfer-ownership annotations
                 transfer = 'none'
-
-        if is_object is None:
-            is_object = (param.type.name == 'GObject.Object' or
-                         (self._namespace_name == 'GObject' and
-                          param.type.name == 'Object'))
-
-        # Default to full transfer for GObjects
-        if isinstance(param, Parameter):
-            is_out = (param.direction != PARAM_DIRECTION_IN)
         else:
-            is_out = True
-        if param.transfer is None or param.transfer_inferred:
-            if is_out and is_object:
-                param.transfer = 'full'
-            elif transfer is not None:
-                param.transfer = transfer
+            transfer = 'full'
+
+        param.transfer = transfer
 
     def _adjust_throws(self, func):
         if func.parameters == []:
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index c3d34d6..bc84da0 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -142,7 +142,8 @@ class Transformer(object):
                 self._names.aliases[node.name] = (nsname, node)
             elif isinstance(node, (GLibBoxed, Interface, Class)):
                 self._names.type_names[node.type_name] = (nsname, node)
-            self._names.names[node.name] = (nsname, node)
+            giname = '%s.%s' % (nsname, node.name)
+            self._names.names[giname] = (nsname, node)
             if hasattr(node, 'ctype'):
                 self._names.ctypes[node.ctype] = (nsname, node)
             elif hasattr(node, 'symbol'):
@@ -366,7 +367,7 @@ class Transformer(object):
                 "symbol %r of type %s" % (symbol.ident, ctype_name(ctype)))
         return node
 
-    def _parse_ctype(self, ctype):
+    def parse_ctype(self, ctype):
         # First look up the ctype including any pointers;
         # a few type names like 'char*' have their own aliases
         # and we need pointer information for those.
@@ -394,29 +395,29 @@ class Transformer(object):
         if ctype in self._list_ctypes:
             param = options.get('element-type')
             if param:
-                contained_type = self._parse_ctype(param[0])
+                contained_type = self.parse_ctype(param[0])
             else:
                 contained_type = None
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = List(derefed_name,
                            ctype,
                            contained_type)
         elif ctype in self._map_ctypes:
             param = options.get('element-type')
             if param:
-                key_type = self._parse_ctype(param[0])
-                value_type = self._parse_ctype(param[1])
+                key_type = self.parse_ctype(param[0])
+                value_type = self.parse_ctype(param[1])
             else:
                 key_type = None
                 value_type = None
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = Map(derefed_name,
                           ctype,
                           key_type, value_type)
         elif (ctype in default_array_types) or ('array' in options):
             derefed_name = ctype[:-1] if ctype[-1] == '*' else ctype
             rettype = Array(ctype,
-                            self._parse_ctype(derefed_name))
+                            self.parse_ctype(derefed_name))
             array_opts = dict([opt.split('=')
                                for opt in options.get('array', [])])
             if 'length' in array_opts:
@@ -425,7 +426,7 @@ class Transformer(object):
                 rettype.size = array_opts['fixed-size']
                 rettype.zeroterminated = False
         else:
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = Type(derefed_name, ctype)
 
         # Deduce direction for some types passed by reference that
diff --git a/tests/everything/Makefile.am b/tests/everything/Makefile.am
index 8f3eceb..2d2e3c3 100644
--- a/tests/everything/Makefile.am
+++ b/tests/everything/Makefile.am
@@ -35,6 +35,8 @@ BUILT_SOURCES = $(TYPELIBS) $(TXMLS) $(GIRS)
 Everything-$(TYPELIB_VERSION).gir: libgirepository-everything.la gitesttypes.c gitesttypes.h $(SCANNER) $(SCANNER_LIBS)
 	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
 	--add-include-path=$(top_builddir)/gir \
+	--uninstalled-introspection-srcdir=$(top_srcdir) \
+	--uninstalled-introspection-builddir=$(top_builddir) \
 	--include=GObject-2.0 \
 	--library=girepository-everything \
 	--namespace=Everything --nsversion=$(TYPELIB_VERSION) \
diff --git a/tests/scanner/Makefile.am b/tests/scanner/Makefile.am
index 9fba3b0..10cb9e7 100644
--- a/tests/scanner/Makefile.am
+++ b/tests/scanner/Makefile.am
@@ -43,9 +43,12 @@ EXTRA_DIST = $(EXPECTEDGIRS) $(EXPECTEDTGIRS)
 annotation-1.0.gir: libannotation.la annotation.c annotation.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
 	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
 	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+	--uninstalled-introspection-srcdir=$(top_srcdir) \
+	--uninstalled-introspection-builddir=$(top_builddir) \
 	--include=GObject-2.0 \
 	--include=utility-1.0 \
 	--library=annotation \
+	--uninst-library=libannotation.la \
 	--namespace=annotation \
 	--nsversion=1.0 \
 	--pkg gobject-2.0 \
@@ -56,9 +59,12 @@ GIRS += annotation-1.0.gir
 drawable-1.0.gir: libdrawable.la drawable.c drawable.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
 	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
 	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+	--uninstalled-introspection-srcdir=$(top_srcdir) \
+	--uninstalled-introspection-builddir=$(top_builddir) \
 	--include=GObject-2.0 \
 	--include=utility-1.0 \
 	--library=drawable \
+	--uninst-library=libdrawable.la \
 	--namespace=drawable \
 	--nsversion=1.0 \
 	--pkg gobject-2.0 \
@@ -75,9 +81,12 @@ EXTRA_DIST += DrawableAdditions.xml
 foo-1.0.gir: libfoo.la foo.c foo.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
 	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
 	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+	--uninstalled-introspection-srcdir=$(top_srcdir) \
+	--uninstalled-introspection-builddir=$(top_builddir) \
 	--include=GObject-2.0 \
 	--include=utility-1.0 \
 	--library=foo \
+	--uninst-library=libfoo.la \
 	--namespace=foo \
 	--nsversion=1.0 \
 	--pkg gobject-2.0 \
@@ -88,8 +97,11 @@ GIRS += foo-1.0.gir
 utility-1.0.gir: libutility.la utility.h $(SCANNER) $(SCANNER_LIBS) Makefile
 	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
 	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+	--uninstalled-introspection-srcdir=$(top_srcdir) \
+	--uninstalled-introspection-builddir=$(top_builddir) \
 	--include=GObject-2.0 \
 	--library=utility \
+	--uninst-library=libutility.la \
 	--namespace=utility \
 	--nsversion=1.0 \
 	--pkg gobject-2.0 \
@@ -101,8 +113,11 @@ GIRS += utility-1.0.gir
 GtkFrob-1.0.gir: libgtkfrob.la gtkfrob.h $(SCANNER) $(SCANNER_LIBS) Makefile
 	PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
 	--add-include-path=$(top_builddir)/gir --add-include-path=. \
+	--uninstalled-introspection-srcdir=$(top_srcdir) \
+	--uninstalled-introspection-builddir=$(top_builddir) \
 	--include=GObject-2.0 \
 	--library=gtkfrob \
+	--uninst-library=libgtkfrob.la \
 	--namespace=GtkFrob \
 	--strip-prefix=Gtk \
 	--nsversion=1.0 \
diff --git a/tests/scanner/annotation-1.0-expected.gir b/tests/scanner/annotation-1.0-expected.gir
index 4f080dc..1a859b3 100644
--- a/tests/scanner/annotation-1.0-expected.gir
+++ b/tests/scanner/annotation-1.0-expected.gir
@@ -62,7 +62,7 @@
           <type name="GObject.Object" c:type="GObject*"/>
         </return-value>
         <parameters>
-          <parameter name="somearg" transfer-ownership="full" allow-none="1">
+          <parameter name="somearg" transfer-ownership="none" allow-none="1">
             <type name="utf8" c:type="gchar*"/>
           </parameter>
         </parameters>
diff --git a/tests/scanner/annotation-1.0-expected.tgir b/tests/scanner/annotation-1.0-expected.tgir
index 0e4c655..9609391 100644
--- a/tests/scanner/annotation-1.0-expected.tgir
+++ b/tests/scanner/annotation-1.0-expected.tgir
@@ -60,7 +60,7 @@
           <type name="GObject.Object"/>
         </return-value>
         <parameters>
-          <parameter name="somearg" transfer-ownership="full" allow-none="1">
+          <parameter name="somearg" transfer-ownership="none" allow-none="1">
             <type name="utf8"/>
           </parameter>
         </parameters>
diff --git a/tests/scanner/annotation.c b/tests/scanner/annotation.c
index bcfe55f..ef521a2 100644
--- a/tests/scanner/annotation.c
+++ b/tests/scanner/annotation.c
@@ -247,7 +247,7 @@ annotation_object_compute_sum_n(AnnotationObject *object,
  * @somearg: (allow-none):
  **/
 GObject*
-annotation_object_allow_none (AnnotationObject *object, gchar *somearg)
+annotation_object_allow_none (AnnotationObject *object, const gchar *somearg)
 {
   return NULL;
 }
diff --git a/tests/scanner/annotation.h b/tests/scanner/annotation.h
index ea78786..3eb9fcb 100644
--- a/tests/scanner/annotation.h
+++ b/tests/scanner/annotation.h
@@ -39,7 +39,7 @@ gint     annotation_object_out          (AnnotationObject *object,
 					 int              *outarg);
 GObject* annotation_object_create_object(AnnotationObject *object);
 GObject* annotation_object_allow_none   (AnnotationObject *object,
-					 gchar            *somearg);
+					 const gchar      *somearg);
 GObject* annotation_object_notrans      (AnnotationObject *object);
 gint     annotation_object_inout        (AnnotationObject *object,
 					 int              *inoutarg);
diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir
index 762c648..8421523 100644
--- a/tests/scanner/foo-1.0-expected.gir
+++ b/tests/scanner/foo-1.0-expected.gir
@@ -157,7 +157,7 @@
           <type name="utf8" c:type="gchararray"/>
         </return-value>
         <parameters>
-          <parameter name="object" transfer-ownership="full">
+          <parameter name="object" transfer-ownership="none">
             <type name="GObject.Object" c:type="GObject"/>
           </parameter>
           <parameter name="p0" transfer-ownership="none">
diff --git a/tests/scanner/foo-1.0-expected.tgir b/tests/scanner/foo-1.0-expected.tgir
index efe696c..465df88 100644
--- a/tests/scanner/foo-1.0-expected.tgir
+++ b/tests/scanner/foo-1.0-expected.tgir
@@ -101,7 +101,7 @@
           <type name="utf8"/>
         </return-value>
         <parameters>
-          <parameter name="object" transfer-ownership="full">
+          <parameter name="object" transfer-ownership="none">
             <type name="GObject.Object"/>
           </parameter>
           <parameter name="p0" transfer-ownership="none">
diff --git a/tools/g-ir-scanner b/tools/g-ir-scanner
index 82bbf34..7d9be34 100755
--- a/tools/g-ir-scanner
+++ b/tools/g-ir-scanner
@@ -23,6 +23,7 @@ import subprocess
 import optparse
 import os
 import sys
+import tempfile
 
 # This only works on unix systems
 currentdir = os.path.dirname(os.path.abspath(sys.argv[0]))
@@ -61,12 +62,24 @@ def _get_option_parser():
     parser.add_option("--add-include-path",
                       action="append", dest="include_paths", default=[],
                       help="include paths for other GIR files")
+    parser.add_option("", "--program",
+                      action="store", dest="program", default=None,
+                      help="program to execute")
     parser.add_option("-l", "--library",
                       action="append", dest="libraries", default=[],
                       help="libraries of this unit")
+    parser.add_option("", "--uninst-library",
+                      action="append", dest="uninstalled_libraries", default=[],
+                      help="override libraries; useful for dealing with libtool")
     parser.add_option("-L", "--library-path",
                       action="append", dest="library_paths", default=[],
                       help="directories to search for libraries")
+    parser.add_option("", "--uninstalled-introspection-srcdir",
+                      action="store", dest="uninstalled_introspection_srcdir",
+                      help=("path to uninstalled libgirepository"))
+    parser.add_option("", "--uninstalled-introspection-builddir",
+                      action="store", dest="uninstalled_introspection_builddir",
+                      help=("path to uninstalled libgirepository"))
     parser.add_option("-n", "--namespace",
                       action="store", dest="namespace_name",
                       help=("name of namespace for this unit, also "
@@ -182,6 +195,88 @@ def validate(assertions, path):
     print "=== PASSED %s ===" % (assertions, )
     return 0
 
+def compile_introspection_binary(options):
+    if options.program:
+        return options.program
+    (fd, c_path) = tempfile.mkstemp('.c', 'tmp-introspect')
+    f = os.fdopen(fd, 'w')
+    f.write('''#include <glib.h>
+#include <girepository.h>
+#include <string.h>
+
+int
+main(int argc, char **argv)
+{
+  const char *prefix = "--introspect=";
+  if (!(argc == 2 && g_str_has_prefix (argv[1], prefix)))
+    {
+      g_printerr ("usage: tmp-introspect --introspect=types.txt,out.xml\\n");
+      return 1;
+    }
+  g_type_init ();
+  g_thread_init (NULL);
+
+  g_irepository_dump (argv[1] + strlen (prefix));
+  return 0;
+}
+''')
+    f.close();
+
+    (fd, o_path) = tempfile.mkstemp('.o', 'tmp-introspect')
+    os.close(fd)
+
+    cc = os.environ.get('CC', 'gcc')
+    ld = os.environ.get('LD', cc)
+
+    pkgs = ['gio-2.0 gthread-2.0']
+    if not options.uninstalled_introspection_srcdir:
+        pkgs.append('gobject-introspection-1.0')
+
+    cc_args = [cc]
+    output = subprocess.Popen(['pkg-config', '--cflags'] + pkgs,
+                              stdout=subprocess.PIPE).communicate()[0]
+    if options.uninstalled_introspection_srcdir:
+        cc_args.append('-I' + os.path.join(options.uninstalled_introspection_srcdir, 'girepository'))
+    cc_args.extend(output.split())
+    for include in options.cpp_includes:
+        cc_args.append('-I' + include)
+    cc_args.extend(['-c', '-o', o_path, c_path])
+    print "%r" % (cc_args, )
+    subprocess.check_call(cc_args, stdout=sys.stdout, stderr=sys.stderr)
+
+    (fd, bin_path) = tempfile.mkstemp('', 'tmp-introspect')
+    os.close(fd)
+
+    ld_args = [ld, '-o', bin_path, o_path]
+    libtool_infection = False
+    for x in options.uninstalled_libraries:
+        if x.endswith('.la'):
+            libtool_infection = True
+            break
+    if options.uninstalled_introspection_srcdir or libtool_infection:
+        ld_args.insert(0, 'libtool')
+        ld_args.insert(1,'--mode=link')
+    output = subprocess.Popen(['pkg-config', '--libs'] + pkgs,
+                              stdout=subprocess.PIPE).communicate()[0]
+    ld_args.extend(output.split())
+
+    # This hack is only for building gobject-introspection itself
+    if options.uninstalled_introspection_builddir:
+        ld_args.append(os.path.join(options.uninstalled_introspection_builddir,
+                                    'girepository', 'libgirepository.la'))
+
+    if options.uninstalled_libraries:
+        for lib in options.uninstalled_libraries:
+            ld_args.append(lib)
+    else:
+        for lib in options.libraries:
+            ld_args.append('-l'+lib)
+    print "%r" % (ld_args, )
+    subprocess.check_call(ld_args, stdout=sys.stdout, stderr=sys.stderr)
+
+    os.unlink(c_path)
+    return [bin_path, o_path]
+
 def main(args):
     parser = _get_option_parser()
     (options, args) = parser.parse_args(args)
@@ -209,8 +304,8 @@ def main(args):
     else:
         _error("Unknown format: %s" % (options.format, ))
 
-    if not options.libraries:
-        _error("Must specify --library at least one primary library")
+    if not (options.libraries or options.program):
+        _error("Must specify --program or --library")
     libraries = options.libraries
 
     for package in options.packages:
@@ -287,12 +382,12 @@ def main(args):
         include_obj = Include.from_string(include)
         transformer.register_include(include_obj)
 
+    binary = compile_introspection_binary(options)
+
     # Transform the C AST nodes into higher level
     # GLib/GObject nodes
     glibtransformer = GLibTransformer(transformer, noclosure=options.noclosure)
-    if options.libraries:
-        for library in options.libraries:
-            glibtransformer.add_library(library)
+    glibtransformer.set_introspection_binary(binary)
 
     namespace = glibtransformer.parse()
 
