cpw.gillux.detachablepurple: 14c4e310: Temporary added some of the yet unreleas...

gillux at soc.pidgin.im gillux at soc.pidgin.im
Thu May 19 16:21:13 EDT 2011


----------------------------------------------------------------------
Revision: 14c4e310f1830a05a41b1898e2b7a4dff51b047a
Parent:   b558e372319c3389461082f11b4fe54a03becb04
Author:   gillux at soc.pidgin.im
Date:     05/19/11 14:23:57
Branch:   im.pidgin.cpw.gillux.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/14c4e310f1830a05a41b1898e2b7a4dff51b047a

Changelog: 

Temporary added some of the yet unreleased glib 2.30 code we will need.
Unfortunately, this code relies on libffi so I also temporary added it
to the build {c,ld}flags.

Changes against parent b558e372319c3389461082f11b4fe54a03becb04

  added    libpurple/glib-2.30.c
  added    libpurple/glib-2.30.h
  patched  configure.ac
  patched  libpurple/Makefile.am

-------------- next part --------------
============================================================
--- configure.ac	ea8767af992e1c49f4f4342a2d5f4c609bc3a2b4
+++ configure.ac	e04a5fae688b0ff25e902a3ffa611b0d820372e3
@@ -340,6 +340,20 @@ AC_SUBST(GLIB_LIBS)
 AC_SUBST(GLIB_CFLAGS)
 AC_SUBST(GLIB_LIBS)
 
+dnl ######################################################################
+dnl ### Libffi
+dnl ### We temporary cut'n'pasted some bits of GLib 2.30, for convenience,
+dnl ### because GLib 2.30 isn't released yet. But those bits refer to libffi,
+dnl ### so we must link with it too. Remove this when GLib 2.30 is released!
+dnl ######################################################################
+PKG_CHECK_MODULES(LIBFFI, [libffi], , [AC_MSG_RESULT(no)
+        AC_MSG_ERROR([
+
+You must have libffi.
+])])
+AC_SUBST(LIBFFI_CFLAGS)
+AC_SUBST(LIBFFI_LIBS)
+
 dnl #####################################
 dnl ### GLib marshall generator
 dnl #####################################
============================================================
--- libpurple/Makefile.am	aee05de606cd29bd9227149da97969e027e5cf9a
+++ libpurple/Makefile.am	79c96e27a874752a61f0ac452ad2c17958a2f931
@@ -342,7 +342,8 @@ dbus_sources  = dbus-server.c dbus-usefu
 	dbus/connection.c \
 	dbus/contact.c \
 	dbus/blist.c \
-	dbus/group.c
+	dbus/group.c \
+	glib-2.30.c
 
 dbus_headers  = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus-types.h \
 	dbus/constructor.h \
@@ -353,7 +354,8 @@ dbus_headers  = dbus-bindings.h dbus-pur
 	dbus/connection.h \
 	dbus/contact.h \
 	dbus/blist.h \
-	dbus/group.h
+	dbus/group.h \
+	glib-2.30.h
 
 dbus_exported = dbus-useful.h dbus-define-api.h account.h accountlist.h blist.h buddyicon.h \
                 connection.h conversation.h core.h ft.h log.h notify.h prefs.h roomlist.h \
@@ -471,6 +473,7 @@ libpurple_la_LIBADD = \
 	$(GSTREAMER_LIBS) \
 	$(GSTINTERFACES_LIBS) \
 	$(IDN_LIBS) \
+	$(LIBFFI_LIBS) \
 	-lm
 
 AM_CPPFLAGS = \
@@ -487,6 +490,7 @@ AM_CPPFLAGS = \
 	$(GSTREAMER_CFLAGS) \
 	$(GSTINTERFACES_CFLAGS) \
 	$(IDN_CFLAGS) \
+	$(LIBFFI_CFLAGS) \
 	$(NETWORKMANAGER_CFLAGS)
 
 # INSTALL_SSL_CERTIFICATES is true when SSL_CERTIFICATES_DIR is empty.
============================================================
--- /dev/null	
+++ libpurple/glib-2.30.c	9cdfdc43ce8bb05898402c84af97319493601fb1
@@ -0,0 +1,610 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Author: David Zeuthen <davidz at redhat.com>
+ */
+
+#include <glib-object.h>
+
+#if !GLIB_CHECK_VERSION(2, 30, 0)
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "glib-2.30.h"
+
+//#include "glibintl.h"
+
+/**
+ * g_dbus_gvariant_to_gvalue:
+ * @value: A #GVariant.
+ * @out_gvalue: Return location pointing to a zero-filled (uninitialized) #GValue.
+ *
+ * Converts a #GVariant to a #GValue. If @value is floating, it is consumed.
+ *
+ * The rules specified in the g_dbus_gvalue_to_gvariant() function are
+ * used - this function is essentially its reverse form.
+ *
+ * The conversion never fails - a valid #GValue is always returned in
+ * @out_gvalue.
+ *
+ * Since: 2.30
+ */
+void
+g_dbus_gvariant_to_gvalue (GVariant  *value,
+                           GValue    *out_gvalue)
+{
+  const GVariantType *type;
+  gchar **array;
+
+  g_return_if_fail (value != NULL);
+  g_return_if_fail (out_gvalue != NULL);
+
+  memset (out_gvalue, '\0', sizeof (GValue));
+
+  switch (g_variant_classify (value))
+    {
+    case G_VARIANT_CLASS_BOOLEAN:
+      g_value_init (out_gvalue, G_TYPE_BOOLEAN);
+      g_value_set_boolean (out_gvalue, g_variant_get_boolean (value));
+      break;
+
+    case G_VARIANT_CLASS_BYTE:
+      g_value_init (out_gvalue, G_TYPE_UCHAR);
+      g_value_set_uchar (out_gvalue, g_variant_get_byte (value));
+      break;
+
+    case G_VARIANT_CLASS_INT16:
+      g_value_init (out_gvalue, G_TYPE_INT);
+      g_value_set_int (out_gvalue, g_variant_get_int16 (value));
+      break;
+
+    case G_VARIANT_CLASS_UINT16:
+      g_value_init (out_gvalue, G_TYPE_UINT);
+      g_value_set_uint (out_gvalue, g_variant_get_uint16 (value));
+      break;
+
+    case G_VARIANT_CLASS_INT32:
+      g_value_init (out_gvalue, G_TYPE_INT);
+      g_value_set_int (out_gvalue, g_variant_get_int32 (value));
+      break;
+
+    case G_VARIANT_CLASS_UINT32:
+      g_value_init (out_gvalue, G_TYPE_UINT);
+      g_value_set_uint (out_gvalue, g_variant_get_uint32 (value));
+      break;
+
+    case G_VARIANT_CLASS_INT64:
+      g_value_init (out_gvalue, G_TYPE_INT64);
+      g_value_set_int64 (out_gvalue, g_variant_get_int64 (value));
+      break;
+
+    case G_VARIANT_CLASS_UINT64:
+      g_value_init (out_gvalue, G_TYPE_UINT64);
+      g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
+      break;
+
+    case G_VARIANT_CLASS_HANDLE:
+      g_value_init (out_gvalue, G_TYPE_INT);
+      g_value_set_int (out_gvalue, g_variant_get_int32 (value));
+      break;
+
+    case G_VARIANT_CLASS_DOUBLE:
+      g_value_init (out_gvalue, G_TYPE_DOUBLE);
+      g_value_set_double (out_gvalue, g_variant_get_double (value));
+      break;
+
+    case G_VARIANT_CLASS_STRING:
+      g_value_init (out_gvalue, G_TYPE_STRING);
+      g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
+      break;
+
+    case G_VARIANT_CLASS_OBJECT_PATH:
+      g_value_init (out_gvalue, G_TYPE_STRING);
+      g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
+      break;
+
+    case G_VARIANT_CLASS_SIGNATURE:
+      g_value_init (out_gvalue, G_TYPE_STRING);
+      g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
+      break;
+
+    case G_VARIANT_CLASS_ARRAY:
+      type = g_variant_get_type (value);
+      switch (g_variant_type_peek_string (type)[1])
+        {
+        case G_VARIANT_CLASS_BYTE:
+          g_value_init (out_gvalue, G_TYPE_STRING);
+          g_value_set_string (out_gvalue, g_variant_get_bytestring (value));
+          break;
+
+        case G_VARIANT_CLASS_STRING:
+          g_value_init (out_gvalue, G_TYPE_STRV);
+          array = g_variant_dup_strv (value, NULL);
+          g_value_take_boxed (out_gvalue, array);
+          break;
+
+        case G_VARIANT_CLASS_ARRAY:
+          switch (g_variant_type_peek_string (type)[2])
+            {
+            case G_VARIANT_CLASS_BYTE:
+              g_value_init (out_gvalue, G_TYPE_STRV);
+              array = g_variant_dup_bytestring_array (value, NULL);
+              g_value_take_boxed (out_gvalue, array);
+              break;
+
+            default:
+              g_value_init (out_gvalue, G_TYPE_VARIANT);
+              g_value_set_variant (out_gvalue, value);
+              break;
+            }
+          break;
+
+        default:
+          g_value_init (out_gvalue, G_TYPE_VARIANT);
+          g_value_set_variant (out_gvalue, value);
+          break;
+        }
+      break;
+
+    case G_VARIANT_CLASS_VARIANT:
+    case G_VARIANT_CLASS_MAYBE:
+    case G_VARIANT_CLASS_TUPLE:
+    case G_VARIANT_CLASS_DICT_ENTRY:
+      g_value_init (out_gvalue, G_TYPE_VARIANT);
+      g_value_set_variant (out_gvalue, value);
+      break;
+    }
+}
+
+
+/**
+ * g_dbus_gvalue_to_gvariant:
+ * @gvalue: A #GValue to convert to a #GVariant.
+ * @type: A #GVariantType.
+ *
+ * Converts a #GValue to a #GVariant of the type indicated by the @type parameter.
+ *
+ * The conversion is using the following rules:
+ * <table frame='all'>
+ *   <title>#GValue / #GVariant conversion rules</title>
+ *   <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ *     <thead>
+ *       <row>
+ *         <entry>If the #GType for @gvalue is...</entry>
+ *         <entry>... then @type must be</entry>
+ *       </row>
+ *     </thead>
+ *     <tbody>
+ *       <row>
+ *         <entry>#G_TYPE_STRING</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-STRING:CAPS">'s'</link>, <link linkend="G-VARIANT-TYPE-OBJECT-PATH:CAPS">'o'</link>, <link linkend="G-VARIANT-TYPE-SIGNATURE:CAPS">'g'</link> or <link linkend="G-VARIANT-TYPE-BYTESTRING:CAPS">'ay'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_STRV</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-STRING-ARRAY:CAPS">'as'</link> or <link linkend="G-VARIANT-TYPE-BYTESTRING-ARRAY:CAPS">'aay'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_BOOLEAN</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-BOOLEAN:CAPS">'b'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_UCHAR</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-BYTE:CAPS">'y'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_INT</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-INT32:CAPS">'i'</link> or <link linkend="G-VARIANT-TYPE-INT16:CAPS">'n'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_UINT</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-UINT32:CAPS">'u'</link> or <link linkend="G-VARIANT-TYPE-UINT16:CAPS">'q'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_INT64</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-INT64:CAPS">'x'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_UINT64</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-UINT64:CAPS">'t'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_INT</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-HANDLE:CAPS">'h'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_DOUBLE</entry>
+ *         <entry><link linkend="G-VARIANT-TYPE-DOUBLE:CAPS">'d'</link></entry>
+ *       </row>
+ *       <row>
+ *         <entry>#G_TYPE_VARIANT</entry>
+ *         <entry>Any #GVariantType</entry>
+ *       </row>
+ *     </tbody>
+ *   </tgroup>
+ * </table>
+ * This can fail if e.g. @gvalue is of type #G_TYPE_STRING and @type
+ * is <link linkend="G-VARIANT-TYPE-INT32:CAPS">'i'</link>. It will
+ * also fail for any #GType (including e.g. #G_TYPE_OBJECT and
+ * #G_TYPE_BOXED derived-types) not in the table above.
+ *
+ * Note that if @gvalue is of type #G_TYPE_VARIANT and its value is
+ * %NULL, the <emphasis>empty</emphasis> #GVariant instance (never
+ * %NULL) for @type is returned (e.g. 0 for scalar types, the empty
+ * string for string types, <literal>'/'</literal> for object path
+ * types, the empty array for any array type and so on).
+ *
+ * See the g_dbus_gvariant_to_gvalue() function for how to convert a
+ * #GVariant to a #GValue.
+ *
+ * Returns: A #GVariant (never floating) of #GVariantType
+ * @type holding the data from @gvalue or %NULL in case of
+ * failure. Free with g_variant_unref().
+ *
+ * Since: 2.30
+ */
+GVariant *
+g_dbus_gvalue_to_gvariant (const GValue       *gvalue,
+                           const GVariantType *type)
+{
+  GVariant *ret;
+  const gchar *s;
+  const gchar * const *as;
+  const gchar *empty_strv[1] = {NULL};
+
+  g_return_val_if_fail (gvalue != NULL, NULL);
+  g_return_val_if_fail (type != NULL, NULL);
+
+  ret = NULL;
+
+  /* @type can easily be e.g. "s" with the GValue holding a GVariant - for example this
+   * can happen when using the org.gtk.GDBus.C.ForceGVariant annotation with the
+   * gdbus-codegen(1) tool.
+   */
+  if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT)
+    {
+      ret = g_value_dup_variant (gvalue);
+    }
+  else
+    {
+      switch (g_variant_type_peek_string (type)[0])
+        {
+        case G_VARIANT_CLASS_BOOLEAN:
+          ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_BYTE:
+          ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_INT16:
+          ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_UINT16:
+          ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_INT32:
+          ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_UINT32:
+          ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_INT64:
+          ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_UINT64:
+          ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_HANDLE:
+          ret = g_variant_ref_sink (g_variant_new_handle (g_value_get_int (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_DOUBLE:
+          ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
+          break;
+
+        case G_VARIANT_CLASS_STRING:
+          s = g_value_get_string (gvalue);
+          if (s == NULL)
+            s = "";
+          ret = g_variant_ref_sink (g_variant_new_string (s));
+          break;
+
+        case G_VARIANT_CLASS_OBJECT_PATH:
+          s = g_value_get_string (gvalue);
+          if (s == NULL)
+            s = "/";
+          ret = g_variant_ref_sink (g_variant_new_object_path (s));
+          break;
+
+        case G_VARIANT_CLASS_SIGNATURE:
+          s = g_value_get_string (gvalue);
+          if (s == NULL)
+            s = "";
+          ret = g_variant_ref_sink (g_variant_new_signature (s));
+          break;
+
+        case G_VARIANT_CLASS_ARRAY:
+          switch (g_variant_type_peek_string (type)[1])
+            {
+            case G_VARIANT_CLASS_BYTE:
+              s = g_value_get_string (gvalue);
+              if (s == NULL)
+                s = "";
+              ret = g_variant_ref_sink (g_variant_new_bytestring (s));
+              break;
+
+            case G_VARIANT_CLASS_STRING:
+              as = g_value_get_boxed (gvalue);
+              if (as == NULL)
+                as = empty_strv;
+              ret = g_variant_ref_sink (g_variant_new_strv (as, -1));
+              break;
+
+            case G_VARIANT_CLASS_ARRAY:
+              switch (g_variant_type_peek_string (type)[2])
+                {
+                case G_VARIANT_CLASS_BYTE:
+                  as = g_value_get_boxed (gvalue);
+                  if (as == NULL)
+                    as = empty_strv;
+                  ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1));
+                  break;
+
+                default:
+                  ret = g_value_dup_variant (gvalue);
+                  break;
+                }
+              break;
+
+            default:
+              ret = g_value_dup_variant (gvalue);
+              break;
+            }
+          break;
+
+        default:
+        case G_VARIANT_CLASS_VARIANT:
+        case G_VARIANT_CLASS_MAYBE:
+        case G_VARIANT_CLASS_TUPLE:
+        case G_VARIANT_CLASS_DICT_ENTRY:
+          ret = g_value_dup_variant (gvalue);
+          break;
+        }
+    }
+
+  /* Could be that the GValue is holding a NULL GVariant - in that case,
+   * we return an "empty" GVariant instead of a NULL GVariant
+   */
+  if (ret == NULL)
+    {
+      GVariant *untrusted_empty;
+      untrusted_empty = g_variant_new_from_data (type, NULL, 0, FALSE, NULL, NULL);
+      ret = g_variant_ref_sink (g_variant_get_normal_form (untrusted_empty));
+      g_variant_unref (untrusted_empty);
+    }
+
+  g_assert (!g_variant_is_floating (ret));
+
+  return ret;
+}
+
+#include <ffi.h>
+static ffi_type *
+value_to_ffi_type (const GValue *gvalue, gpointer *value)
+{
+  ffi_type *rettype = NULL;
+  GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
+  g_assert (type != G_TYPE_INVALID);
+
+  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_STRING:
+    case G_TYPE_OBJECT:
+    case G_TYPE_BOXED:
+    case G_TYPE_POINTER:
+    case G_TYPE_INTERFACE:
+    case G_TYPE_VARIANT:
+      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 ("value_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));
+      break;
+    }
+  return rettype;
+}
+
+static void
+value_from_ffi_type (GValue *gvalue, gpointer *value)
+{
+  switch (g_type_fundamental (G_VALUE_TYPE (gvalue)))
+    {
+    case G_TYPE_INT:
+      g_value_set_int (gvalue, *(gint*)value);
+      break;
+    case G_TYPE_FLOAT:
+      g_value_set_float (gvalue, *(gfloat*)value);
+      break;
+    case G_TYPE_DOUBLE:
+      g_value_set_double (gvalue, *(gdouble*)value);
+      break;
+    case G_TYPE_BOOLEAN:
+      g_value_set_boolean (gvalue, *(gboolean*)value);
+      break;
+    case G_TYPE_STRING:
+      g_value_set_string (gvalue, *(gchar**)value);
+      break;
+    case G_TYPE_CHAR:
+      g_value_set_char (gvalue, *(gchar*)value);
+      break;
+    case G_TYPE_UCHAR:
+      g_value_set_uchar (gvalue, *(guchar*)value);
+      break;
+    case G_TYPE_UINT:
+      g_value_set_uint (gvalue, *(guint*)value);
+      break;
+    case G_TYPE_POINTER:
+      g_value_set_pointer (gvalue, *(gpointer*)value);
+      break;
+    case G_TYPE_LONG:
+      g_value_set_long (gvalue, *(glong*)value);
+      break;
+    case G_TYPE_ULONG:
+      g_value_set_ulong (gvalue, *(gulong*)value);
+      break;
+    case G_TYPE_INT64:
+      g_value_set_int64 (gvalue, *(gint64*)value);
+      break;
+    case G_TYPE_UINT64:
+      g_value_set_uint64 (gvalue, *(guint64*)value);
+      break;
+    case G_TYPE_BOXED:
+      g_value_set_boxed (gvalue, *(gpointer*)value);
+      break;
+    default:
+      g_warning ("value_from_ffi_type: Unsupported fundamental type: %s",
+                g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))));
+    }
+}
+
+/**
+ * g_cclosure_marshal_generic:
+ * @closure: A #GClosure.
+ * @return_gvalue: A #GValue to store the return value. May be %NULL
+ *   if the callback of closure doesn't return a value.
+ * @n_param_values: The length of the @param_values array.
+ * @param_values: An array of #GValue<!-- -->s holding the arguments
+ *   on which to invoke the callback of closure.
+ * @invocation_hint: The invocation hint given as the last argument to
+ *   g_closure_invoke().
+ * @marshal_data: Additional data specified when registering the
+ *   marshaller, see g_closure_set_marshal() and
+ *   g_closure_set_meta_marshal()
+ *
+ * A generic marshaller function implemented via <ulink
+ * url="http://sourceware.org/libffi/">libffi</ulink>.
+ *
+ * Since: 2.30
+ */
+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 && G_VALUE_TYPE (return_gvalue))
+    {
+      rtype = value_to_ffi_type (return_gvalue, &rvalue);
+    }
+  else
+    {
+      rtype = &ffi_type_void;
+    }
+
+  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);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      atypes[n_args-1] = value_to_ffi_type (param_values + 0,
+                                            &args[n_args-1]);
+      atypes[0] = &ffi_type_pointer;
+      args[0] = &closure->data;
+    }
+  else
+    {
+      atypes[0] = 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] = value_to_ffi_type (param_values + i, &args[i]);
+
+  if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
+    return;
+
+  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);
+}
+
+#endif /* !GLIB_CHECK_VERSION(2, 30, 0) */
+
============================================================
--- /dev/null	
+++ libpurple/glib-2.30.h	759285b92dc69f38d763a434a3b3569a1f66349a
@@ -0,0 +1,59 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Author: David Zeuthen <davidz at redhat.com>
+ */
+#ifndef __GLIB_STUFF__
+#define __GLIB_STUFF__
+
+#include <glib-object.h>
+
+#if !GLIB_CHECK_VERSION(2, 30, 0)
+
+/* Cut'n'pasted missing bits of the glib. From git 8148a3c396a76012da6fc2241128a2b428c818ff. */
+G_BEGIN_DECLS
+
+void g_dbus_gvariant_to_gvalue (GVariant  *value,
+                                GValue    *out_gvalue);
+GVariant *g_dbus_gvalue_to_gvariant (const GValue         *gvalue,
+                                     const GVariantType   *type);
+
+/* FIXME:
+   OK:  data_object::destroy            -> closure_invalidate();
+   MIS: closure_invalidate()            -> disconnect(closure);
+   MIS: disconnect(closure)             -> (unlink) closure_unref();
+   OK:  closure_finalize()              -> g_free (data_string);
+
+   random remarks:
+   - need marshaller repo with decent aliasing to base types
+   - provide marshaller collection, virtually covering anything out there
+*/
+
+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_END_DECLS
+
+#endif /* !GLIB_CHECK_VERSION(2, 30, 0) */
+
+#endif /* __GLIB_STUFF__ */


More information about the Commits mailing list