[gobject-introspection] girffi: Fix g_callable_info_prepare_closure for certain callables



commit d8970fbc500a8b20853b564536251315587450d9
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Apr 9 17:51:08 2012 -0300

    girffi: Fix g_callable_info_prepare_closure for certain callables
    
    Namely, those that are methods and those that throw GErrors.
    We have very similar code in two places that calculate arg lengths and
    argument types to stick into libffi. Merge, clean up, and correct both.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=673805

 girepository/girffi.c |  115 +++++++++++++++++++------------------------------
 1 files changed, 44 insertions(+), 71 deletions(-)
---
diff --git a/girepository/girffi.c b/girepository/girffi.c
index f6e47fb..ec710c3 100644
--- a/girepository/girffi.c
+++ b/girepository/girffi.c
@@ -146,42 +146,65 @@ g_type_info_get_ffi_type (GITypeInfo *info)
 /**
  * g_callable_info_get_ffi_arg_types:
  * @callable_info: a callable info from a typelib
+ * @n_args_p: (out): The number of arguments
  *
  * Return value: an array of ffi_type*. The array itself
  * should be freed using g_free() after use.
  */
 static ffi_type **
-g_callable_info_get_ffi_arg_types (GICallableInfo *callable_info)
+g_callable_info_get_ffi_arg_types (GICallableInfo *callable_info,
+                                   int            *n_args_p)
 {
     ffi_type **arg_types;
-    gint n_args, i;
+    gboolean is_method, throws;
+    gint n_args, n_invoke_args, i, offset;
 
     g_return_val_if_fail (callable_info != NULL, NULL);
 
     n_args = g_callable_info_get_n_args (callable_info);
+    is_method = g_callable_info_is_method (callable_info);
+    throws = g_callable_info_can_throw_gerror (callable_info);
+    offset = is_method ? 1 : 0;
 
-    arg_types = (ffi_type **) g_new0 (ffi_type *, n_args + 1);
+    n_invoke_args = n_args;
+
+    if (is_method)
+      n_invoke_args++;
+    if (throws)
+      n_invoke_args++;
+
+    if (n_args_p)
+      *n_args_p = n_invoke_args;
+
+    arg_types = (ffi_type **) g_new0 (ffi_type *, n_invoke_args + 1);
+
+    if (is_method)
+      arg_types[0] = &ffi_type_pointer;
+    if (throws)
+      arg_types[n_invoke_args - 1] = &ffi_type_pointer;
 
     for (i = 0; i < n_args; ++i)
       {
-        GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
-        GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
-        switch (g_arg_info_get_direction (arg_info))
+        GIArgInfo arg_info;
+        GITypeInfo arg_type;
+
+        g_callable_info_load_arg (callable_info, i, &arg_info);
+        g_arg_info_load_type (&arg_info, &arg_type);
+        switch (g_arg_info_get_direction (&arg_info))
           {
             case GI_DIRECTION_IN:
-              arg_types[i] = g_type_info_get_ffi_type (arg_type);
+              arg_types[i + offset] = g_type_info_get_ffi_type (&arg_type);
               break;
             case GI_DIRECTION_OUT:
             case GI_DIRECTION_INOUT:
-              arg_types[i] = &ffi_type_pointer;
+              arg_types[i + offset] = &ffi_type_pointer;
               break;
             default:
               g_assert_not_reached ();
           }
-        g_base_info_unref ((GIBaseInfo *)arg_info);
-        g_base_info_unref ((GIBaseInfo *)arg_type);
       }
-    arg_types[n_args] = NULL;
+
+    arg_types[n_invoke_args] = NULL;
 
     return arg_types;
 }
@@ -275,71 +298,19 @@ g_function_invoker_new_for_address (gpointer           addr,
                                     GIFunctionInvoker *invoker,
                                     GError           **error)
 {
-  ffi_type *rtype;
   ffi_type **atypes;
-  GITypeInfo *tinfo;
-  GIArgInfo *ainfo;
-  GIInfoType info_type;
-  gboolean is_method;
-  gboolean throws;
-  gint n_args, n_invoke_args, i;
+  gint n_args;
 
   g_return_val_if_fail (info != NULL, FALSE);
   g_return_val_if_fail (invoker != NULL, FALSE);
 
   invoker->native_address = addr;
 
-  is_method = g_callable_info_is_method (info);
-  throws = g_callable_info_can_throw_gerror (info);
-
-  tinfo = g_callable_info_get_return_type (info);
-  rtype = g_type_info_get_ffi_type (tinfo);
-  g_base_info_unref ((GIBaseInfo *)tinfo);
-
-  n_args = g_callable_info_get_n_args (info);
-  if (is_method)
-    n_invoke_args = n_args+1;
-  else
-    n_invoke_args = n_args;
-
-  if (throws)
-    /* Add an argument for the GError */
-    n_invoke_args ++;
-
-  /* TODO: avoid malloc here? */
-  atypes = g_malloc0 (sizeof (ffi_type*) * n_invoke_args);
+  atypes = g_callable_info_get_ffi_arg_types (info, &n_args);
 
-  if (is_method)
-    {
-      atypes[0] = &ffi_type_pointer;
-    }
-  for (i = 0; i < n_args; i++)
-    {
-      int offset = (is_method ? 1 : 0);
-      ainfo = g_callable_info_get_arg (info, i);
-      switch (g_arg_info_get_direction (ainfo))
-        {
-          case GI_DIRECTION_IN:
-            tinfo = g_arg_info_get_type (ainfo);
-            atypes[i+offset] = g_type_info_get_ffi_type (tinfo);
-            g_base_info_unref ((GIBaseInfo *)tinfo);
-            break;
-          case GI_DIRECTION_OUT:
-          case GI_DIRECTION_INOUT:
-            atypes[i+offset] = &ffi_type_pointer;
-    	    break;
-          default:
-            g_assert_not_reached ();
-        }
-      g_base_info_unref ((GIBaseInfo *)ainfo);
-    }
-
-  if (throws)
-    {
-      atypes[n_invoke_args - 1] = &ffi_type_pointer;
-    }
-
-  return ffi_prep_cif (&(invoker->cif), FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) == FFI_OK;
+  return ffi_prep_cif (&(invoker->cif), FFI_DEFAULT_ABI, n_args,
+                       g_callable_info_get_ffi_return_type (info),
+                       atypes) == FFI_OK;
 }
 
 /**
@@ -380,6 +351,8 @@ g_callable_info_prepare_closure (GICallableInfo       *callable_info,
                                  gpointer              user_data)
 {
   gpointer exec_ptr;
+  int n_args;
+  ffi_type **atypes;
   GIClosureWrapper *closure;
   ffi_status status;
 
@@ -395,10 +368,10 @@ g_callable_info_prepare_closure (GICallableInfo       *callable_info,
     }
   closure->writable_self = closure;
 
-  status = ffi_prep_cif (cif, FFI_DEFAULT_ABI,
-                         g_callable_info_get_n_args (callable_info),
+  atypes = g_callable_info_get_ffi_arg_types (callable_info, &n_args);
+  status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, n_args,
                          g_callable_info_get_ffi_return_type (callable_info),
-                         g_callable_info_get_ffi_arg_types (callable_info));
+                         atypes);
   if (status != FFI_OK)
     {
       g_warning ("ffi_prep_cif failed: %d\n", status);



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