[pygobject] Unify Python interface struct to GI marshaling code



commit 6d3a0751e71ee3c37b3bb646723aed75971e5b39
Author: Simon Feltman <sfeltman src gnome org>
Date:   Thu Mar 28 22:41:51 2013 -0700

    Unify Python interface struct to GI marshaling code
    
    Add pygi_marshal_from_py_interface_struct used for direct gi method
    call in args and vfunc out args.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=693405

 gi/pygi-argument.c        |   75 +++++++-------------
 gi/pygi-cache.c           |   12 +---
 gi/pygi-marshal-from-py.c |  167 ++++++++++++++++++++++++++++-----------------
 gi/pygi-marshal-from-py.h |   11 +++
 4 files changed, 141 insertions(+), 124 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 8cc467c..9540f5a 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -1143,56 +1143,31 @@ array_success:
                 case GI_INFO_TYPE_STRUCT:
                 case GI_INFO_TYPE_UNION:
                 {
-                    GType type;
-
-                    if (object == Py_None) {
-                        arg.v_pointer = NULL;
-                        break;
-                    }
-
-                    type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
-
-                    /* Handle special cases first. */
-                    if (g_type_is_a (type, G_TYPE_VALUE)) {
-                        g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
-                        /* This will currently leak the GValue that is allocated and
-                         * stashed in arg.v_pointer. Out argument marshaling for caller
-                         * allocated GValues already pass in memory for the GValue.
-                         * Further re-factoring is needed to fix this leak.
-                         * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405
-                         */
-                        pygi_marshal_from_py_gvalue (object,
-                                                     &arg,
-                                                     transfer,
-                                                     FALSE /*is_allocated*/);
-
-                    } else if (g_type_is_a (type, G_TYPE_CLOSURE)) {
-                        pygi_marshal_from_py_gclosure (object, &arg);
-                    } else if (g_struct_info_is_foreign (info)) {
-                        pygi_struct_foreign_convert_to_g_argument (object, info, transfer, &arg);
-                    } else if (g_type_is_a (type, G_TYPE_BOXED)) {
-                        if (pyg_boxed_check (object, type)) {
-                            arg.v_pointer = pyg_boxed_get (object, void);
-                            if (transfer == GI_TRANSFER_EVERYTHING) {
-                                arg.v_pointer = g_boxed_copy (type, arg.v_pointer);
-                            }
-                        } else {
-                            PyErr_Format (PyExc_TypeError, "wrong boxed type");
-                        }
-                    } else if (g_type_is_a (type, G_TYPE_POINTER) || 
-                               g_type_is_a (type, G_TYPE_VARIANT) || 
-                               type == G_TYPE_NONE) {
-                        g_warn_if_fail (g_type_is_a (type, G_TYPE_VARIANT) || !g_type_info_is_pointer 
(type_info) || transfer == GI_TRANSFER_NOTHING);
-
-                        if (g_type_is_a (type, G_TYPE_VARIANT) && pyg_type_from_object (object) != 
G_TYPE_VARIANT) {
-                            PyErr_SetString (PyExc_TypeError, "expected GLib.Variant");
-                            break;
-                        }
-                        arg.v_pointer = pyg_pointer_get (object, void);
-                    } else {
-                        PyErr_Format (PyExc_NotImplementedError, "structure type '%s' is not supported yet", 
g_type_name (type));
-                    }
-
+                    GType g_type;
+                    PyObject *py_type;
+
+                    g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
+                    py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info);
+
+                    /* Note for G_TYPE_VALUE g_type:
+                     * This will currently leak the GValue that is allocated and
+                     * stashed in arg.v_pointer. Out argument marshaling for caller
+                     * allocated GValues already pass in memory for the GValue.
+                     * Further re-factoring is needed to fix this leak.
+                     * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405
+                     */
+                    pygi_marshal_from_py_interface_struct (object,
+                                                           &arg,
+                                                           NULL, /*arg_name*/
+                                                           info, /*interface_info*/
+                                                           type_info,
+                                                           g_type,
+                                                           py_type,
+                                                           transfer,
+                                                           FALSE, /*is_caller_allocates*/
+                                                           g_struct_info_is_foreign (info));
+
+                    Py_DECREF (py_type);
                     break;
                 }
                 case GI_INFO_TYPE_ENUM:
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 99f49cf..d149732 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -756,6 +756,7 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
 
             break;
+        case GI_INFO_TYPE_BOXED:
         case GI_INFO_TYPE_STRUCT:
             if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
                _arg_cache_from_py_interface_struct_setup (arg_cache,
@@ -776,17 +777,6 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
 
             break;
-        case GI_INFO_TYPE_BOXED:
-            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
-                _arg_cache_from_py_interface_struct_setup (arg_cache,
-                                                       iface_info,
-                                                       transfer);
-
-            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
-                _arg_cache_to_py_interface_struct_setup (arg_cache,
-                                                      iface_info,
-                                                      transfer);
-            break;
         case GI_INFO_TYPE_CALLBACK:
             {
                 PyGICallbackCache *callback_cache;
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index 5858e68..639a226 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -194,19 +194,19 @@ gi_argument_from_c_long (GIArgument *arg_out,
  * expected C union
  */
 static gboolean
-_is_union_member (PyGIInterfaceCache *iface_cache, PyObject *py_arg) {
+_is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) {
     gint i;
     gint n_fields;
     GIUnionInfo *union_info;
     GIInfoType info_type;
     gboolean is_member = FALSE;
 
-    info_type = g_base_info_get_type (iface_cache->interface_info);
+    info_type = g_base_info_get_type (interface_info);
 
     if (info_type != GI_INFO_TYPE_UNION)
         return FALSE;
 
-    union_info = (GIUnionInfo *) iface_cache->interface_info;
+    union_info = (GIUnionInfo *) interface_info;
     n_fields = g_union_info_get_n_fields (union_info);
 
     for (i = 0; i < n_fields; i++) {
@@ -1643,65 +1643,16 @@ _pygi_marshal_from_py_interface_struct (PyGIInvokeState   *state,
 {
     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
 
-    if (py_arg == Py_None) {
-        arg->v_pointer = NULL;
-        return TRUE;
-    }
-
-    /* FIXME: handle this large if statement in the cache
-     *        and set the correct marshaller
-     */
-
-    if (iface_cache->g_type == G_TYPE_CLOSURE) {
-        return pygi_marshal_from_py_gclosure (py_arg, arg);
-    } else if (iface_cache->g_type == G_TYPE_VALUE) {
-        return pygi_marshal_from_py_gvalue(py_arg, arg,
-                                           arg_cache->transfer,
-                                           arg_cache->is_caller_allocates);
-    } else if (iface_cache->is_foreign) {
-        PyObject *success;
-        success = pygi_struct_foreign_convert_to_g_argument (py_arg,
-                                                             iface_cache->interface_info,
-                                                             arg_cache->transfer,
-                                                             arg);
-
-        return (success == Py_None);
-    } else if (!PyObject_IsInstance (py_arg, iface_cache->py_type)) {
-        /* first check to see if this is a member of the expected union */
-        if (!_is_union_member (iface_cache, py_arg)) {
-            if (!PyErr_Occurred()) {
-                PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
-
-                PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
-                              arg_cache->arg_name ? arg_cache->arg_name : "self",
-                              iface_cache->type_name,
-                              module ? PYGLIB_PyUnicode_AsString(module) : "",
-                              module ? "." : "",
-                              py_arg->ob_type->tp_name);
-                if (module)
-                    Py_DECREF (module);
-            }
-
-            return FALSE;
-        }
-    }
-
-    if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
-        arg->v_pointer = pyg_boxed_get (py_arg, void);
-        if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
-            arg->v_pointer = g_boxed_copy (iface_cache->g_type, arg->v_pointer);
-        }
-    } else if (g_type_is_a (iface_cache->g_type, G_TYPE_POINTER) ||
-                   g_type_is_a (iface_cache->g_type, G_TYPE_VARIANT) ||
-                       iface_cache->g_type  == G_TYPE_NONE) {
-        arg->v_pointer = pyg_pointer_get (py_arg, void);
-    } else {
-        PyErr_Format (PyExc_NotImplementedError,
-                      "structure type '%s' is not supported yet",
-                      g_type_name(iface_cache->g_type));
-        return FALSE;
-    }
-    return TRUE;
+    return pygi_marshal_from_py_interface_struct (py_arg,
+                                                  arg,
+                                                  arg_cache->arg_name,
+                                                  iface_cache->interface_info,
+                                                  arg_cache->type_info,
+                                                  iface_cache->g_type,
+                                                  iface_cache->py_type,
+                                                  arg_cache->transfer,
+                                                  arg_cache->is_caller_allocates,
+                                                  iface_cache->is_foreign);
 }
 
 gboolean
@@ -1775,7 +1726,7 @@ gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState   *state,
 
             if (!PyObject_IsInstance (py_arg, iface_cache->py_type)) {
                 /* wait, we might be a member of a union so manually check */
-                if (!_is_union_member (iface_cache, py_arg)) {
+                if (!_is_union_member (iface_cache->interface_info, py_arg)) {
                     if (!PyErr_Occurred()) {
                         PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
                         PyErr_Format (PyExc_TypeError,
@@ -1979,3 +1930,93 @@ pygi_marshal_from_py_gclosure(PyObject *py_arg,
     arg->v_pointer = closure;
     return TRUE;
 }
+
+gboolean
+pygi_marshal_from_py_interface_struct (PyObject *py_arg,
+                                       GIArgument *arg,
+                                       const gchar *arg_name,
+                                       GIBaseInfo *interface_info,
+                                       GITypeInfo *type_info,
+                                       GType g_type,
+                                       PyObject *py_type,
+                                       GITransfer transfer,
+                                       gboolean is_allocated,
+                                       gboolean is_foreign)
+{
+    if (py_arg == Py_None) {
+        arg->v_pointer = NULL;
+        return TRUE;
+    }
+
+    /* FIXME: handle this large if statement in the cache
+     *        and set the correct marshaller
+     */
+
+    if (g_type_is_a (g_type, G_TYPE_CLOSURE)) {
+        return pygi_marshal_from_py_gclosure (py_arg, arg);
+    } else if (g_type_is_a (g_type, G_TYPE_VALUE)) {
+        return pygi_marshal_from_py_gvalue(py_arg,
+                                           arg,
+                                           transfer,
+                                           is_allocated);
+    } else if (is_foreign) {
+        PyObject *success;
+        success = pygi_struct_foreign_convert_to_g_argument (py_arg,
+                                                             interface_info,
+                                                             transfer,
+                                                             arg);
+
+        return (success == Py_None);
+    } else if (!PyObject_IsInstance (py_arg, py_type)) {
+        /* first check to see if this is a member of the expected union */
+        if (!_is_union_member (interface_info, py_arg)) {
+            if (!PyErr_Occurred()) {
+                gchar *type_name = _pygi_g_base_info_get_fullname (interface_info);
+                PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
+
+                PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
+                              arg_name ? arg_name : "self",
+                              type_name,
+                              module ? PYGLIB_PyUnicode_AsString(module) : "",
+                              module ? "." : "",
+                              py_arg->ob_type->tp_name);
+                if (module)
+                    Py_DECREF (module);
+                g_free (type_name);
+            }
+
+            return FALSE;
+        }
+    }
+
+    if (g_type_is_a (g_type, G_TYPE_BOXED)) {
+        if (pyg_boxed_check (py_arg, g_type)) {
+            arg->v_pointer = pyg_boxed_get (py_arg, void);
+            if (transfer == GI_TRANSFER_EVERYTHING) {
+                arg->v_pointer = g_boxed_copy (g_type, arg->v_pointer);
+            }
+        } else {
+            PyErr_Format (PyExc_TypeError, "wrong boxed type");
+            return FALSE;
+        }
+
+    } else if (g_type_is_a (g_type, G_TYPE_POINTER) ||
+               g_type_is_a (g_type, G_TYPE_VARIANT) ||
+               g_type  == G_TYPE_NONE) {
+        g_warn_if_fail (g_type_is_a (g_type, G_TYPE_VARIANT) || !g_type_info_is_pointer (type_info) || 
transfer == GI_TRANSFER_NOTHING);
+
+        if (g_type_is_a (g_type, G_TYPE_VARIANT) &&
+                pyg_type_from_object (py_arg) != G_TYPE_VARIANT) {
+            PyErr_SetString (PyExc_TypeError, "expected GLib.Variant");
+            return FALSE;
+        }
+        arg->v_pointer = pyg_pointer_get (py_arg, void);
+
+    } else {
+        PyErr_Format (PyExc_NotImplementedError,
+                      "structure type '%s' is not supported yet",
+                      g_type_name(g_type));
+        return FALSE;
+    }
+    return TRUE;
+}
diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h
index e0a57d3..307d716 100644
--- a/gi/pygi-marshal-from-py.h
+++ b/gi/pygi-marshal-from-py.h
@@ -198,6 +198,17 @@ gboolean pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/
 gboolean pygi_marshal_from_py_gclosure(PyObject *py_arg, /*in*/
                                        GIArgument *arg); /*out*/
 
+gboolean pygi_marshal_from_py_interface_struct (PyObject *py_arg,
+                                                GIArgument *arg,
+                                                const gchar *arg_name,
+                                                GIBaseInfo *interface_info,
+                                                GITypeInfo *type_info,
+                                                GType g_type,
+                                                PyObject *py_type,
+                                                GITransfer transfer,
+                                                gboolean is_allocated,
+                                                gboolean is_foreign);
+
 G_END_DECLS
 
 #endif /* __PYGI_MARSHAL_from_py_PY__ */


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