[pygobject/invoke-rewrite] [gi] flesh out interface in marshalling a bit more



commit 4fcca8518774ab89607196dfc52037e3da30ac8a
Author: John (J5) Palmieri <johnp redhat com>
Date:   Tue Jan 11 13:49:58 2011 -0500

    [gi] flesh out interface in marshalling a bit more

 gi/pygi-argument.c |   74 +++++++++++++++++++++++++++++++++++++++---------
 gi/pygi-cache.c    |   79 ++++++++++++++++++++++++++++++++++++++++-----------
 gi/pygi-cache.h    |    1 +
 3 files changed, 123 insertions(+), 31 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 49d41b5..19df4d6 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -2718,21 +2718,60 @@ _pygi_marshal_in_interface_struct (PyGIInvokeState   *state,
                                    PyObject          *py_arg,
                                    GIArgument        *arg)
 {
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
-    return FALSE;
-}
+    PyGIIntefaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
 
-gboolean
-_pygi_marshal_in_interface_interface (PyGIInvokeState   *state,
-                                      PyGIFunctionCache *function_cache,
-                                      PyGIArgCache      *arg_cache,
-                                      PyObject          *py_arg,
-                                      GIArgument        *arg)
-{
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
-    return FALSE;
+    if (py_arg == Py_None) {
+        arg.v_pointer = NULL;
+        return TRUE;
+    }
+
+    if (iface_cache->g_type == G_TYPE_CLOSURE) {
+        GClosure *closure;
+        if (!PyCallable_Check (py_arg)) {
+            PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
+                          py_arg->ob_type->tp_name);
+            return FALSE;
+        }
+
+        closure = pyg_closure_new (py_arg, NULL, NULL);
+        if (closure == NULL) {
+            PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
+            return FALSE;
+        }
+
+        (*argv).v_pointer = closure;
+    } else if (iface_cache->g_type == G_VALUE) {
+        GValue *value;
+        GType object_type;
+
+        object_type = pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
+        if (object_type == G_TYPE_INVALID) {
+            PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
+            return FALSE;
+        }
+
+        value = g_slice_new0 (GValue);
+        g_value_init (value, object_type);
+        if (pyg_value_from_pyobject (value, object) < 0) {
+            g_slice_free (GValue, value);
+            PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
+            return FALSE;
+        }
+
+        (*arg).v_pointer = value;
+
+    } else if (iface_cache->is_foreign) {
+         PyErr_Format (PyExc_NotImplementedError, "foreign types not implemented yet");
+
+        return FALSE;
+    } else if (!PyObject_IsInstance (py_arg, iface_cache->py_type)) {
+        PyErr_Format (PyExc_TypeError, "Expected %s, but got %s",
+                      iface_cache->type_name, 
+                      iface_cache->py_type->ob_type->tp_name);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 gboolean
@@ -2759,6 +2798,13 @@ _pygi_marshal_in_interface_object (PyGIInvokeState   *state,
         return TRUE;
     }
 
+    if (!PyObject_IsInstance (py_arg, ((PyGIInterfaceCache *)arg_cache)->py_type)) {
+        PyErr_Format (PyExc_TypeError, "Expected %s, but got %s",
+                      ((PyGIInterfaceCache *)arg_cache)->type_name, 
+                      ((PyGIInterfaceCache *)arg_cache)->py_type->ob_type->tp_name);
+        return FALSE;
+    }
+
     (*arg).v_pointer = pygobject_get (py_arg);
     if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
         g_object_ref ((*arg).v_pointer);
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index af4f704..ff92de9 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -18,8 +18,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  * USA
  */
+
+#include "pygi-info.h"
 #include "pygi-cache.h"
 #include "pygi-argument.h"
+#include "pygi-type.h"
 #include <girepository.h>
 
 PyGIArgCache * _arg_cache_in_new_from_type_info (GITypeInfo *type_info,
@@ -36,6 +39,8 @@ _interface_cache_free_func (PyGIInterfaceCache *cache)
     if (cache != NULL) {
         Py_XDECREF(cache->py_type);
         g_slice_free(PyGIInterfaceCache, cache);
+        if (cache->type_name != NULL)
+            g_free(cache->type_name);
     }
 }
 
@@ -103,6 +108,7 @@ _function_cache_new_from_function_info(GIFunctionInfo *function_info)
     flags = g_function_info_get_flags(function_info);
     fc->is_method = flags & GI_FUNCTION_IS_METHOD;
     fc->is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR;
+
     fc->n_args = g_callable_info_get_n_args ( (GICallableInfo *) function_info) + (fc->is_method ? 1: 0);
     if (fc->n_args > 0)
         fc->args_cache = g_slice_alloc0(fc->n_args * sizeof(PyGIArgCache *));
@@ -110,6 +116,29 @@ _function_cache_new_from_function_info(GIFunctionInfo *function_info)
     return fc;
 }
 
+
+static inline PyGIInterfaceCache *
+_interface_cache_new_from_interface_info(GIInterfaceInfo *iface_info)
+{
+    PyGIInterfaceCache *ic;
+    
+    ic = g_slice_new0(PyGIInterfaceCache);
+    ((PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;    
+    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
+    if (ic->g_type != G_TYPE_NONE) {
+        ic->py_type = _pygi_type_get_from_g_type (ic->g_type);
+    } else {
+        /* FIXME: avoid passing GI infos to noncache API */
+        ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
+    }
+
+    if (ic->py_type == NULL)
+        return NULL;
+
+    ic->type_name == _pygi_g_base_info_get_fullname(iface_info);
+    return ic;
+}
+
 static inline PyGISequenceCache *
 _sequence_cache_new_from_type_info(GITypeInfo *type_info)
 {
@@ -118,6 +147,7 @@ _sequence_cache_new_from_type_info(GITypeInfo *type_info)
     GITypeTag item_type_tag;
 
     sc = g_slice_new0(PyGISequenceCache);
+    ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;    
 
     sc->fixed_size = -1;
     sc->len_arg_index = -1;
@@ -146,8 +176,6 @@ _sequence_cache_new_from_type_info(GITypeInfo *type_info)
     sc->item_cache->type_tag = item_type_tag;    
     g_base_info_unref( (GIBaseInfo *) item_type_info);
 
-    ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
-
     return sc;
 }
 
@@ -355,20 +383,33 @@ _arg_cache_new_for_in_interface_union(void)
     return arg_cache;
 }
 
+
+static void 
+_g_slice_free_gvalue_func(GValue *value) {
+    g_slice_free(GValue, value);
+}
+
 static inline PyGIArgCache *
-_arg_cache_new_for_in_interface_struct(void)
+_arg_cache_new_for_in_interface_struct(GIInterfaceInfo *iface_info,
+                                       GITransfer transfer)
 {
-    PyGIArgCache *arg_cache = NULL;
-    /*arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;*/
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Caching for this type is not fully implemented yet");
+    PyGIInterfaceCache *iface_cache = _interface_cache_new_from_interface_info(iface_info);
+    PyGIArgCache *arg_cache = (PyGIArgCache *)iface_cache);
+    iface_cache->is_foreign = g_struct_info_is_foreign( (GIStructInfo*)iface_info);
+    arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
+    if (iface_cache->g_type == G_TYPE_VALUE)
+        arg_cache->cleanup = _g_slice_free_gvalue_func;
+    if (iface_cache->g_type == G_TYPE_CLOSURE)
+        arg_cache->cleanup = g_closure_unref;
+
     return arg_cache;
 }
 
 static inline PyGIArgCache *
-_arg_cache_new_for_in_interface_object(GITransfer transfer)
+_arg_cache_new_for_in_interface_object(GIInterfaceInfo *iface_info,
+                                       GITransfer transfer)
 {
-    PyGIArgCache *arg_cache = _arg_cache_new();
+    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
     arg_cache->in_marshaller = _pygi_marshal_in_interface_object;
     if (transfer == GI_TRANSFER_EVERYTHING)
         arg_cache->cleanup = (GDestroyNotify)g_object_unref;
@@ -377,12 +418,11 @@ _arg_cache_new_for_in_interface_object(GITransfer transfer)
 }
 
 static inline PyGIArgCache *
-_arg_cache_new_for_in_interface_boxed(void)
+_arg_cache_new_for_in_interface_boxed(GIInterfaceInfo *iface_info,
+                                      GITransfer transfer)
 {
-    PyGIArgCache *arg_cache = NULL;
-    /*arg_cache->in_marshaller = _pygi_marshal_in_boxed;*/
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Caching for this type is not fully implemented yet");
+    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
+    arg_cache->in_marshaller = _pygi_marshal_in_interface_boxed;
     return arg_cache;
 }
 
@@ -436,10 +476,12 @@ _arg_cache_in_new_from_interface_info (GIInterfaceInfo *iface_info,
             break;
         case GI_INFO_TYPE_OBJECT:
         case GI_INFO_TYPE_INTERFACE:
-            arg_cache = _arg_cache_new_for_in_interface_object(transfer);
+            arg_cache = _arg_cache_new_for_in_interface_object(iface_info,
+                                                               transfer);
             break;
         case GI_INFO_TYPE_BOXED:
-            arg_cache = _arg_cache_new_for_in_interface_boxed();
+            arg_cache = _arg_cache_new_for_in_interface_boxed(iface_info,
+                                                              transfer);
             break;
         case GI_INFO_TYPE_CALLBACK:
             arg_cache = _arg_cache_new_for_in_interface_callback();
@@ -461,6 +503,8 @@ _arg_cache_in_new_from_interface_info (GIInterfaceInfo *iface_info,
         arg_cache->py_arg_index = py_arg_index;
         arg_cache->c_arg_index = c_arg_index;
     }
+
+    return arg_cache;
 }
 
 
@@ -604,7 +648,8 @@ _args_cache_generate(GIFunctionInfo *function_info,
         function_cache->n_in_args++;
     }
 
-    for (arg_index; arg_index < function_cache->n_args; arg_index++) {
+
+    for (; arg_index < function_cache->n_args; arg_index++) {
         PyGIArgCache *arg_cache = NULL;
         GIArgInfo *arg_info;
         GITypeInfo *type_info;
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 00780db..310839e 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -76,6 +76,7 @@ typedef struct _PyGIInterfaceCache
     gboolean is_foreign;
     GType g_type;
     PyObject *py_type;
+    gchar *type_name;
 } PyGIInterfaceCache;
 
 typedef struct _PyGIHashCache



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