[template-glib] eval: allow some basic calling of raw GI functions



commit 7816c975a1b364b26f719cbcf33202691d36173d
Author: Christian Hergert <chergert redhat com>
Date:   Mon Oct 23 16:34:22 2017 -0700

    eval: allow some basic calling of raw GI functions
    
    If we have a GIFunction that is part of a namespace, we should
    be able to call that function. One such example would be
    GObject.type_is_a(GType,GType). This makes that particular
    function work.
    
    This GI call dispatch function is getting pretty hairy, but that
    is a problem for another day.

 src/tmpl-expr-eval.c |   55 +++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 50 insertions(+), 5 deletions(-)
---
diff --git a/src/tmpl-expr-eval.c b/src/tmpl-expr-eval.c
index c0c6dc0..b78377a 100644
--- a/src/tmpl-expr-eval.c
+++ b/src/tmpl-expr-eval.c
@@ -668,12 +668,14 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
   GIFunctionInfo *function = NULL;
   GIArgument return_value_arg = { 0 };
   GITypeInfo return_value_type;
+  GIArgument *dispatch_args = NULL;
   TmplExpr *args;
   GObject *object;
   gboolean ret = FALSE;
   GArray *in_args = NULL;
   GArray *values = NULL;
   GType type;
+  guint dispatch_len = 0;
   guint n_args;
   guint i;
 
@@ -787,6 +789,44 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
       goto cleanup;
     }
 
+  repository = g_irepository_get_default ();
+
+  if (G_VALUE_HOLDS (&left, TMPL_TYPE_TYPELIB) &&
+      g_value_get_pointer (&left) != NULL)
+    {
+      GITypelib *typelib = g_value_get_pointer (&left);
+      const gchar *ns = g_typelib_get_namespace (typelib);
+
+      base_info = g_irepository_find_by_name (repository, ns, node->name);
+
+      if (!GI_IS_FUNCTION_INFO (base_info))
+        {
+          g_set_error (error,
+                       TMPL_ERROR,
+                       TMPL_ERROR_GI_FAILURE,
+                       "%s is not a function in %s",
+                       node->name, ns);
+          goto cleanup;
+        }
+
+      function = (GIFunctionInfo *)base_info;
+
+      n_args = g_callable_info_get_n_args ((GICallableInfo *)function);
+
+      values = g_array_new (FALSE, TRUE, sizeof (GValue));
+      g_array_set_clear_func (values, (GDestroyNotify)g_value_unset);
+      g_array_set_size (values, n_args);
+
+      in_args = g_array_new (FALSE, TRUE, sizeof (GIArgument));
+      g_array_set_size (in_args, n_args + 1);
+
+      /* Skip past first param, which is used for Object below */
+      dispatch_args = ((GIArgument *)(gpointer)in_args->data) + 1;
+      dispatch_len = in_args->len - 1;
+
+      goto apply_args;
+    }
+
   if (!G_VALUE_HOLDS_OBJECT (&left))
     {
       g_set_error (error,
@@ -808,7 +848,6 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
       goto cleanup;
     }
 
-  repository = g_irepository_get_default ();
   type = G_OBJECT_TYPE (object);
 
   while (g_type_is_a (type, G_TYPE_OBJECT))
@@ -827,6 +866,7 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
           goto cleanup;
         }
 
+      /* First locate the function in the object */
       function = g_object_info_find_method ((GIObjectInfo *)base_info, node->name);
       if (function != NULL)
         break;
@@ -838,9 +878,9 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
           GIInterfaceInfo *iface_info;
 
           iface_info = g_object_info_get_interface ((GIObjectInfo *)base_info, i);
-
           function = g_interface_info_find_method (iface_info, node->name);
         }
+
       if (function != NULL)
         break;
 
@@ -868,6 +908,10 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
 
   g_array_index (in_args, GIArgument, 0).v_pointer = object;
 
+  dispatch_args = (GIArgument *)(gpointer)in_args->data;
+  dispatch_len = in_args->len;
+
+apply_args:
   args = node->params;
 
   for (i = 0; i < n_args; i++)
@@ -928,8 +972,8 @@ tmpl_expr_gi_call_eval (TmplExprGiCall  *node,
     }
 
   if (!g_function_info_invoke (function,
-                               (GIArgument *)(void *)in_args->data,
-                               in_args->len,
+                               dispatch_args,
+                               dispatch_len,
                                NULL,
                                0,
                                &return_value_arg,
@@ -1564,7 +1608,8 @@ builtin_typeof (const GValue  *value,
   g_value_init (return_value, G_TYPE_GTYPE);
 
   if (G_VALUE_HOLDS (value, TMPL_TYPE_BASE_INFO) &&
-      g_value_get_pointer (value) != NULL)
+      g_value_get_pointer (value) != NULL &&
+      GI_IS_REGISTERED_TYPE_INFO (g_value_get_pointer (value)))
     g_value_set_gtype (return_value,
                        g_registered_type_info_get_g_type (g_value_get_pointer (value)));
   else if (G_VALUE_HOLDS_OBJECT (value) &&


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