Index: configure.ac
===================================================================
--- configure.ac	(revision 636)
+++ configure.ac	(arbetskopia)
@@ -100,6 +100,26 @@
 
 AM_CHECK_PYMOD(thread,,,enable_thread=no)
 
+# libffi
+AC_MSG_CHECKING(for ffi.h)
+AC_TRY_CPP([#include <ffi.h>], pygobject_ffi_h=yes, pygobject_ffi_h=no)
+if test $pygobject_ffi_h = yes; then
+   AC_DEFINE(HAVE_FFI_H,1,[Have ffi.h include file])
+fi
+AC_MSG_RESULT([$pygobject_ffi_h])
+AM_CONDITIONAL(HAVE_LIBFFI, test "$pygobject_ffi_h" = "yes")
+
+# C/Invoke
+AC_MSG_CHECKING(for cinvoke.h)
+AC_TRY_CPP([#include <cinvoke.h>], 
+           pygobject_cinvoke_h=yes, 
+	   pygobject_cinvoke_h=no)
+if test $pygobject_cinvoke_h = yes; then
+   AC_DEFINE(HAVE_CINVOKE_H,1,[Have ffi.h include file])
+fi
+AC_MSG_RESULT([$pygobject_cinvoke_h])
+AM_CONDITIONAL(HAVE_CINVOKE, test "$pygobject_cinvoke_h" = "yes")
+
 AC_MSG_CHECKING(whether to enable threading in pygobject)
 if test "x$enable_thread" != xno; then
   extra_mods=gthread
Index: gobject/gobjectmodule.c
===================================================================
--- gobject/gobjectmodule.c	(revision 636)
+++ gobject/gobjectmodule.c	(arbetskopia)
@@ -27,6 +27,11 @@
 #include "pygobject-private.h"
 #include "pythread.h"
 #include <gobject/gvaluecollector.h>
+#ifdef HAVE_FFI_H
+#  include <ffi.h>
+#elif HAVE_CINVOKE_H
+#  include <cinvoke.h>
+#endif
 
 static PyObject *gerror_exc = NULL;
 static gboolean use_gil_state_api = FALSE;
@@ -462,6 +467,278 @@
     class->get_property = pyg_object_get_property;
 }
 
+#ifdef HAVE_FFI_H
+static ffi_type *
+g_value_to_ffi_type (const GValue *gvalue, gpointer *value)
+{
+  ffi_type *rettype = NULL;
+  GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
+
+  switch (type) {
+  case G_TYPE_BOOLEAN:
+  case G_TYPE_CHAR:
+  case G_TYPE_INT:
+    rettype = &ffi_type_sint;
+    *value = (gpointer)&(gvalue->data[0].v_int);
+    break;
+  case G_TYPE_UCHAR:
+  case G_TYPE_UINT:
+    rettype = &ffi_type_uint;
+    *value = (gpointer)&(gvalue->data[0].v_uint);
+    break;
+  case G_TYPE_OBJECT:
+  case G_TYPE_STRING:
+  case G_TYPE_POINTER:
+    rettype = &ffi_type_pointer;
+    *value = (gpointer)&(gvalue->data[0].v_pointer);
+    break;
+  case G_TYPE_FLOAT:
+    rettype = &ffi_type_float;
+    *value = (gpointer)&(gvalue->data[0].v_float);
+    break;
+  case G_TYPE_DOUBLE:
+    rettype = &ffi_type_double;
+    *value = (gpointer)&(gvalue->data[0].v_double);
+    break;
+  case G_TYPE_LONG:
+    rettype = &ffi_type_slong;
+    *value = (gpointer)&(gvalue->data[0].v_long);
+    break;
+  case G_TYPE_ULONG:
+    rettype = &ffi_type_ulong;
+    *value = (gpointer)&(gvalue->data[0].v_ulong);
+    break;
+  case G_TYPE_INT64:
+    rettype = &ffi_type_sint64;
+    *value = (gpointer)&(gvalue->data[0].v_int64);
+    break;
+  case G_TYPE_UINT64:
+    rettype = &ffi_type_uint64;
+    *value = (gpointer)&(gvalue->data[0].v_uint64);
+    break;
+  default:
+    rettype = &ffi_type_pointer;
+    *value = NULL;
+    g_warning ("Unsupported fundamental type: %s", g_type_name (type));
+    break;
+  }
+  return rettype;
+}
+
+static void
+g_cclosure_marshal_generic (GClosure *closure,
+			    GValue *return_gvalue,
+			    guint n_param_values,
+			    const GValue *param_values,
+			    gpointer invocation_hint,
+			    gpointer marshal_data)
+
+{
+  ffi_type *rtype;
+  void *rvalue;
+  int n_args;
+  ffi_type **atypes;
+  void **args;
+  int i;
+  ffi_cif cif;
+  GCClosure *cc = (GCClosure*) closure;
+
+  if (return_gvalue) 
+    {
+      rtype = g_value_to_ffi_type (return_gvalue, &rvalue);
+    }
+  else 
+    {
+      rtype = &ffi_type_void;
+      rvalue = NULL;
+    }
+  
+  n_args = n_param_values + 1;
+  atypes = g_new (ffi_type*, n_args);
+  args =  g_new (gpointer, n_args);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      atypes[n_args-1] = g_value_to_ffi_type (param_values + 0,  
+					      &args[n_args-1]);
+      atypes[0] = &ffi_type_pointer;
+      args[0] = &closure->data;
+    }
+  else
+    {
+      atypes[0] = g_value_to_ffi_type (param_values + 0, &args[0]);
+      atypes[n_args-1] = &ffi_type_pointer;
+      args[n_args-1] = &closure->data;
+    }
+
+  for (i = 1; i < n_args - 1; i++)
+    atypes[i] = g_value_to_ffi_type (param_values + i, &args[i]);
+
+  if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
+    goto out;
+
+  ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
+
+ out:
+  g_free (atypes);
+  g_free (args);
+}
+#elif HAVE_CINVOKE_H
+static void 
+g_value_to_cinvoke (const GValue *gvalue, char *format, void **value)
+{
+  GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
+
+  switch (type) {
+  case G_TYPE_BOOLEAN:
+  case G_TYPE_CHAR:
+  case G_TYPE_INT:
+    *format = 'i';
+    *value = (void*)&(gvalue->data[0].v_int);
+    break;
+  case G_TYPE_UCHAR:
+  case G_TYPE_UINT:
+    *format = 'i';
+    *value = (void*)&(gvalue->data[0].v_uint);
+    break;
+  case G_TYPE_OBJECT:
+  case G_TYPE_STRING:
+  case G_TYPE_POINTER:
+    *format = 'p';
+    *value = (void*)&(gvalue->data[0].v_pointer);
+    break;
+  case G_TYPE_FLOAT:
+    *format = 'f';
+    *value = (void*)&(gvalue->data[0].v_float);
+    break;
+  case G_TYPE_DOUBLE:
+    *format = 'd';
+    *value = (void*)&(gvalue->data[0].v_double);
+    break;
+  case G_TYPE_LONG:
+    *format = 'l';
+    *value = (void*)&(gvalue->data[0].v_long);
+    break;
+  case G_TYPE_ULONG:
+    *format = 'l';
+    *value = (void*)&(gvalue->data[0].v_ulong);
+    break;
+  case G_TYPE_INT64:
+    *format = '8';
+    *value = (void*)&(gvalue->data[0].v_int64);
+    break;
+  case G_TYPE_UINT64:
+    *format = '8';
+    *value = (void*)&(gvalue->data[0].v_uint64);
+    break;
+  default:
+    g_warning ("Unsupported fundamental type: %s\n", g_type_name (type));
+    break;
+  }
+}
+
+static void
+g_cclosure_marshal_generic (GClosure *closure,
+			    GValue *return_gvalue,
+			    guint n_param_values,
+			    const GValue *param_values,
+			    gpointer invocation_hint,
+			    gpointer marshal_data)
+{
+  static CInvContext *ctx = NULL;
+  CInvFunction *function;
+  int i;
+  char *return_format;
+  void *return_value;
+  char *parameter_format;
+  void **parameter_values;
+  GCClosure *cc = (GCClosure*) closure;
+
+  if (!ctx)
+    {
+      ctx = cinv_context_create ();
+      if (!ctx) 
+	g_error ("cinv_function_create failed: %s\n",
+		 cinv_context_geterrormsg (ctx));
+    }
+
+  if (return_gvalue) 
+    {
+      return_format = g_new0 (char, 2);
+      g_value_to_cinvoke (return_gvalue, return_format, &return_value);
+    }
+  else 
+    {
+      return_format = "";
+      return_value = NULL;
+    }
+  
+  parameter_format = g_new (char, n_param_values + 2);
+  parameter_values = g_new (void *, n_param_values + 1);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      g_value_to_cinvoke (param_values + 0, 
+			  &parameter_format[n_param_values], 
+			  &parameter_values[n_param_values]);
+      parameter_format[0] = 'p';
+      parameter_values[0] = &closure->data;
+    }
+  else
+    {
+      g_value_to_cinvoke (param_values + 0, 
+			  &parameter_format[0], 
+			  &parameter_values[0]);
+      parameter_format[n_param_values] = 'p';
+      parameter_values[n_param_values] = &closure->data;
+    }
+
+  for (i = 1; i < n_param_values; i++)
+    {
+      g_value_to_cinvoke (param_values + i,
+			  &parameter_format[i],
+			  &parameter_values[i]);
+    }
+  parameter_format[n_param_values+1] = '\0';
+
+  function = cinv_function_create (ctx, CINV_CC_DEFAULT, 
+				   return_format, parameter_format);
+  
+  if (cinv_function_invoke (ctx, function, 
+			    marshal_data ? marshal_data : cc->callback,
+			    return_value,
+			    parameter_values) != CINV_SUCCESS) 
+    {
+      g_error ("cinv_function_invoke failed: %s\n",
+	       cinv_context_geterrormsg (ctx));
+    }
+			   
+  g_free (parameter_format);
+  g_free (parameter_values);
+  if (return_gvalue)
+    g_free (return_format);
+
+  if (cinv_function_delete (ctx, function) != CINV_SUCCESS) 
+    {
+      g_error ("freeing cinvoke function failed: %s\n",
+	       cinv_context_geterrormsg (ctx));
+    }
+}
+#else
+static void
+g_cclosure_marshal_generic (GClosure *closure,
+			    GValue *return_gvalue,
+			    guint n_param_values,
+			    const GValue *param_values,
+			    gpointer invocation_hint,
+			    gpointer marshal_data)
+{
+    g_warning ("Marshalling CClosures are not supported in this version \n"
+	       "of PyGObject, you need to recompile it with libffi or \n"
+	       "C/Invoke support.");
+}
+#endif
+
 typedef struct _PyGSignalAccumulatorData {
     PyObject *callable;
     PyObject *user_data;
@@ -593,7 +870,7 @@
     signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
 			      pyg_signal_class_closure_get(),
 			      accumulator, accum_data,
-			      (GSignalCMarshaller)0,
+			      g_cclosure_marshal_generic,
 			      return_type, n_params, param_types);
     g_free(param_types);
 
Index: gobject/Makefile.am
===================================================================
--- gobject/Makefile.am	(revision 636)
+++ gobject/Makefile.am	(arbetskopia)
@@ -43,3 +43,11 @@
 if PLATFORM_WIN32
 _gobject_la_CFLAGS += -DPLATFORM_WIN32
 endif
+
+if HAVE_LIBFFI
+_gobject_la_LIBADD += -lffi
+else 
+if HAVE_CINVOKE
+_gobject_la_LIBADD += -lcinvoke
+endif
+endif
