summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Feltman <sfeltman@src.gnome.org>2013-10-12 20:00:12 -0700
committerSimon Feltman <sfeltman@src.gnome.org>2014-02-02 16:02:57 -0800
commit1d0f120d77582509b4e75d83f500a1ace7ed6421 (patch)
tree60a470165153f02d97b7b37c15d3371f07aa26b5
parent4dcaa2b988239e01224994098c3e7cbe8b455fe0 (diff)
downloadpygobject-1d0f120d77582509b4e75d83f500a1ace7ed6421.tar.gz
cache refactoring: Move various struct arg setup and marshaling to new file
Move struct (boxed, union, gvalue, gclosure, variant, and pointer) argument cache setup and marshaling fragments into isolated file: pygi-struct-marshal.c. Remove redundant and dead code related to boxed and union marshaling. https://bugzilla.gnome.org/show_bug.cgi?id=709700
-rw-r--r--gi/Makefile.am2
-rw-r--r--gi/pygi-argument.c1
-rw-r--r--gi/pygi-array.c3
-rw-r--r--gi/pygi-cache.c72
-rw-r--r--gi/pygi-cache.h1
-rw-r--r--gi/pygi-marshal-cleanup.c48
-rw-r--r--gi/pygi-marshal-cleanup.h16
-rw-r--r--gi/pygi-marshal-from-py.c288
-rw-r--r--gi/pygi-marshal-from-py.h33
-rw-r--r--gi/pygi-marshal-to-py.c120
-rw-r--r--gi/pygi-marshal-to-py.h27
-rw-r--r--gi/pygi-object.c2
-rw-r--r--gi/pygi-struct-marshal.c516
-rw-r--r--gi/pygi-struct-marshal.h73
14 files changed, 607 insertions, 595 deletions
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 3d153f4d..9c34c034 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -113,6 +113,8 @@ _gi_la_SOURCES = \
pygi-error.h \
pygi-object.c \
pygi-object.h \
+ pygi-struct-marshal.c \
+ pygi-struct-marshal.h \
pygi-hashtable.c \
pygi-hashtable.h
_gi_la_CFLAGS = \
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 4624e0f8..f88ff62d 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -35,6 +35,7 @@
#include "pygi-marshal-to-py.h"
#include "pygi-basictype.h"
#include "pygi-object.h"
+#include "pygi-struct-marshal.h"
static gboolean
diff --git a/gi/pygi-array.c b/gi/pygi-array.c
index 7b515846..22eea53e 100644
--- a/gi/pygi-array.c
+++ b/gi/pygi-array.c
@@ -26,6 +26,9 @@
#include "pygi-private.h"
#include "pygi-marshal-cleanup.h"
+/* Needed for _pygi_marshal_cleanup_from_py_interface_struct_gvalue hack */
+#include "pygi-struct-marshal.h"
+
/*
* GArray to Python
*/
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index f26df8c6..aab25348 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -2,6 +2,7 @@
* vim: tabstop=4 shiftwidth=4 expandtab
*
* Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -34,6 +35,7 @@
#include "pygi-closure.h"
#include "pygi-error.h"
#include "pygi-object.h"
+#include "pygi-struct-marshal.h"
/* _arg_info_default_value
@@ -251,48 +253,6 @@ _arg_cache_alloc (void)
}
static void
-_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
-}
-
-static void
-_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
- GITransfer transfer)
-{
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
-}
-
-static void
-_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
- GIInterfaceInfo *iface_info,
- GITransfer transfer)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
- arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
-
- if (iface_cache->g_type == G_TYPE_VALUE)
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
- else if (iface_cache->is_foreign)
- arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
-}
-
-static void
-_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
- GIInterfaceInfo *iface_info,
- GITransfer transfer)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
- arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
-
- if (iface_cache->is_foreign)
- arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
-}
-
-static void
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
GITransfer transfer)
{
@@ -351,6 +311,14 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
transfer,
direction,
iface_info);
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_UNION:
+ return pygi_arg_struct_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
default:
; /* pass through to old model of setup */
}
@@ -364,26 +332,6 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
return NULL;
switch (info_type) {
- case GI_INFO_TYPE_UNION:
- if (direction & PYGI_DIRECTION_FROM_PYTHON)
- _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
-
- if (direction & PYGI_DIRECTION_TO_PYTHON)
- _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)
- _arg_cache_from_py_interface_struct_setup (arg_cache,
- iface_info,
- transfer);
-
- if (direction & PYGI_DIRECTION_TO_PYTHON)
- _arg_cache_to_py_interface_struct_setup (arg_cache,
- iface_info,
- transfer);
- break;
case GI_INFO_TYPE_ENUM:
if (direction & PYGI_DIRECTION_FROM_PYTHON)
_arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 3cbe2b60..28046f1a 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -2,6 +2,7 @@
* vim: tabstop=4 shiftwidth=4 expandtab
*
* Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index 0bbfab68..3d826016 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -205,51 +205,3 @@ pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state,
{
state->failed = TRUE;
}
-
-void
-_pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- gpointer data,
- gboolean was_processed)
-{
- /* Note py_arg can be NULL for hash table which is a bug. */
- if (was_processed && py_arg != NULL) {
- GType py_object_type =
- pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
-
- /* When a GValue was not passed, it means the marshalers created a new
- * one to pass in, clean this up.
- */
- if (py_object_type != G_TYPE_VALUE) {
- g_value_unset ((GValue *) data);
- g_slice_free (GValue, data);
- }
- }
-}
-
-void
-_pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- gpointer data,
- gboolean was_processed)
-{
- if (state->failed && was_processed)
- pygi_struct_foreign_release (
- ( (PyGIInterfaceCache *)arg_cache)->interface_info,
- data);
-}
-
-void
-_pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- PyObject *dummy,
- gpointer data,
- gboolean was_processed)
-{
- if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- pygi_struct_foreign_release (
- ( (PyGIInterfaceCache *)arg_cache)->interface_info,
- data);
-}
diff --git a/gi/pygi-marshal-cleanup.h b/gi/pygi-marshal-cleanup.h
index 2463cab1..e895f37a 100644
--- a/gi/pygi-marshal-cleanup.h
+++ b/gi/pygi-marshal-cleanup.h
@@ -39,22 +39,6 @@ void pygi_marshal_cleanup_args_return_fail (PyGIInvokeState *state,
void pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state,
PyGICallableCache *cache,
gssize failed_to_py_arg_index);
-
-void _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- gpointer data,
- gboolean was_processed);
-void _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
- PyGIArgCache *arg_cache,
- PyObject *dummy,
- gpointer data,
- gboolean was_processed);
G_END_DECLS
#endif /* __PYGI_MARSHAL_CLEANUP_H__ */
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index ba798591..259f9eaf 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -87,59 +87,6 @@ gi_argument_from_c_long (GIArgument *arg_out,
}
}
-/*
- * _is_union_member - check to see if the py_arg is actually a member of the
- * expected C union
- */
-static gboolean
-_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 (interface_info);
-
- if (info_type != GI_INFO_TYPE_UNION)
- return FALSE;
-
- union_info = (GIUnionInfo *) interface_info;
- n_fields = g_union_info_get_n_fields (union_info);
-
- for (i = 0; i < n_fields; i++) {
- GIFieldInfo *field_info;
- GITypeInfo *field_type_info;
-
- field_info = g_union_info_get_field (union_info, i);
- field_type_info = g_field_info_get_type (field_info);
-
- /* we can only check if the members are interfaces */
- if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) {
- GIInterfaceInfo *field_iface_info;
- PyObject *py_type;
-
- field_iface_info = g_type_info_get_interface (field_type_info);
- py_type = _pygi_type_import_by_gi_info ((GIBaseInfo *) field_iface_info);
-
- if (py_type != NULL && PyObject_IsInstance (py_arg, py_type)) {
- is_member = TRUE;
- }
-
- Py_XDECREF (py_type);
- g_base_info_unref ( ( GIBaseInfo *) field_iface_info);
- }
-
- g_base_info_unref ( ( GIBaseInfo *) field_type_info);
- g_base_info_unref ( ( GIBaseInfo *) field_info);
-
- if (is_member)
- break;
- }
-
- return is_member;
-}
-
gboolean
_pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
@@ -257,238 +204,3 @@ err:
}
-gboolean
-_pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg,
- gpointer *cleanup_data)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
-
- gboolean res = _pygi_marshal_from_py_interface_struct (py_arg,
- arg,
- arg_cache->arg_name,
- iface_cache->interface_info,
- iface_cache->g_type,
- iface_cache->py_type,
- arg_cache->transfer,
- TRUE, /*copy_reference*/
- iface_cache->is_foreign,
- arg_cache->is_pointer);
-
- /* Assume struct marshaling is always a pointer and assign cleanup_data
- * here rather than passing it further down the chain.
- */
- *cleanup_data = arg->v_pointer;
- return res;
-}
-
-gboolean
-_pygi_marshal_from_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg,
- gpointer *cleanup_data)
-{
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return FALSE;
-}
-
-gboolean
-_pygi_marshal_from_py_interface_union (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg,
- gpointer *cleanup_data)
-{
- PyErr_Format(PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return FALSE;
-}
-
-
-/* _pygi_marshal_from_py_gvalue:
- * py_arg: (in):
- * arg: (out):
- * transfer:
- * copy_reference: TRUE if arg should use the pointer reference held by py_arg
- * when it is already holding a GValue vs. copying the value.
- */
-gboolean
-_pygi_marshal_from_py_gvalue (PyObject *py_arg,
- GIArgument *arg,
- GITransfer transfer,
- gboolean copy_reference) {
- 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;
- }
-
- /* if already a gvalue, use that, else marshal into gvalue */
- if (object_type == G_TYPE_VALUE) {
- GValue *source_value = pyg_boxed_get (py_arg, GValue);
- if (copy_reference) {
- value = source_value;
- } else {
- value = g_slice_new0 (GValue);
- g_value_init (value, G_VALUE_TYPE (source_value));
- g_value_copy (source_value, value);
- }
- } else {
- value = g_slice_new0 (GValue);
- g_value_init (value, object_type);
- if (pyg_value_from_pyobject (value, py_arg) < 0) {
- g_slice_free (GValue, value);
- PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
- return FALSE;
- }
- }
-
- arg->v_pointer = value;
- return TRUE;
-}
-
-/* _pygi_marshal_from_py_gclosure:
- * py_arg: (in):
- * arg: (out):
- */
-gboolean
-_pygi_marshal_from_py_gclosure(PyObject *py_arg,
- GIArgument *arg)
-{
- GClosure *closure;
- GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE);
-
- if ( !(PyCallable_Check(py_arg) ||
- g_type_is_a (object_gtype, G_TYPE_CLOSURE))) {
- PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
- py_arg->ob_type->tp_name);
- return FALSE;
- }
-
- if (g_type_is_a (object_gtype, G_TYPE_CLOSURE))
- closure = (GClosure *)pyg_boxed_get (py_arg, void);
- else
- closure = pyg_closure_new (py_arg, NULL, NULL);
-
- if (closure == NULL) {
- PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
- return FALSE;
- }
-
- 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,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean copy_reference,
- gboolean is_foreign,
- gboolean is_pointer)
-{
- gboolean is_union = FALSE;
-
- 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,
- copy_reference);
- } 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 */
- is_union = _is_union_member (interface_info, py_arg);
- if (!is_union) {
- goto type_error;
- }
- }
-
- if (g_type_is_a (g_type, G_TYPE_BOXED)) {
- /* Additionally use pyg_type_from_object to pull the stashed __gtype__
- * attribute off of the input argument for type checking. This is needed
- * to work around type discrepancies in cases with aliased (typedef) types.
- * e.g. GtkAllocation, GdkRectangle.
- * See: https://bugzilla.gnomethere are .org/show_bug.cgi?id=707140
- */
- if (is_union || pyg_boxed_check (py_arg, g_type) ||
- g_type_is_a (pyg_type_from_object (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 {
- goto type_error;
- }
-
- } 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) || !is_pointer || 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);
- if (transfer == GI_TRANSFER_EVERYTHING) {
- g_variant_ref ((GVariant *)arg->v_pointer);
- }
-
- } else {
- PyErr_Format (PyExc_NotImplementedError,
- "structure type '%s' is not supported yet",
- g_type_name(g_type));
- return FALSE;
- }
- return TRUE;
-
-type_error:
- {
- 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;
- }
-}
diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h
index 4b59601e..2daa3810 100644
--- a/gi/pygi-marshal-from-py.h
+++ b/gi/pygi-marshal-from-py.h
@@ -45,18 +45,6 @@ gboolean _pygi_marshal_from_py_interface_flags (PyGIInvokeState *state,
PyObject *py_arg,
GIArgument *arg,
gpointer *cleanup_data);
-gboolean _pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg,
- gpointer *cleanup_data);
-gboolean _pygi_marshal_from_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- PyObject *py_arg,
- GIArgument *arg,
- gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_union (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
@@ -64,27 +52,6 @@ gboolean _pygi_marshal_from_py_interface_union (PyGIInvokeState *state,
GIArgument *arg,
gpointer *cleanup_data);
-/* Simplified marshalers shared between vfunc/closure and direct function calls. */
-
-gboolean _pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/
- GIArgument *arg, /*out*/
- GITransfer transfer,
- gboolean is_allocated);
-
-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,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean is_allocated,
- gboolean is_foreign,
- gboolean is_pointer);
-
G_END_DECLS
#endif /* __PYGI_MARSHAL_from_py_PY__ */
diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c
index 536193c5..8384a42b 100644
--- a/gi/pygi-marshal-to-py.c
+++ b/gi/pygi-marshal-to-py.c
@@ -150,123 +150,3 @@ _pygi_marshal_to_py_interface_flags (PyGIInvokeState *state,
return py_obj;
}
-PyObject *
-_pygi_marshal_to_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
-
- return _pygi_marshal_to_py_interface_struct (arg,
- iface_cache->interface_info,
- iface_cache->g_type,
- iface_cache->py_type,
- arg_cache->transfer,
- arg_cache->is_caller_allocates,
- iface_cache->is_foreign);
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_interface (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_union (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg)
-{
- PyObject *py_obj = NULL;
-
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for this type is not implemented yet");
- return py_obj;
-}
-
-PyObject *
-_pygi_marshal_to_py_interface_struct (GIArgument *arg,
- GIInterfaceInfo *interface_info,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean is_allocated,
- gboolean is_foreign)
-{
- PyObject *py_obj = NULL;
-
- if (arg->v_pointer == NULL) {
- Py_RETURN_NONE;
- }
-
- if (g_type_is_a (g_type, G_TYPE_VALUE)) {
- py_obj = pyg_value_as_pyobject (arg->v_pointer, FALSE);
- } else if (is_foreign) {
- py_obj = pygi_struct_foreign_convert_from_g_argument (interface_info,
- arg->v_pointer);
- } else if (g_type_is_a (g_type, G_TYPE_BOXED)) {
- if (py_type) {
- py_obj = _pygi_boxed_new ((PyTypeObject *) py_type,
- arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING || is_allocated,
- is_allocated ?
- g_struct_info_get_size(interface_info) : 0);
- }
- } else if (g_type_is_a (g_type, G_TYPE_POINTER)) {
- if (py_type == NULL ||
- !PyType_IsSubtype ((PyTypeObject *) py_type, &PyGIStruct_Type)) {
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
- py_obj = pyg_pointer_new (g_type, arg->v_pointer);
- } else {
- py_obj = _pygi_struct_new ( (PyTypeObject *) py_type,
- arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING);
- }
- } else if (g_type_is_a (g_type, G_TYPE_VARIANT)) {
- /* Note: sink the variant (add a ref) only if we are not transfered ownership.
- * GLib.Variant overrides __del__ which will then call "g_variant_unref" for
- * cleanup in either case. */
- if (py_type) {
- if (transfer == GI_TRANSFER_NOTHING) {
- g_variant_ref_sink (arg->v_pointer);
- }
- py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
- arg->v_pointer,
- FALSE);
- }
- } else if (g_type == G_TYPE_NONE) {
- if (py_type) {
- py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
- arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING);
- }
- } else {
- PyErr_Format (PyExc_NotImplementedError,
- "structure type '%s' is not supported yet",
- g_type_name (g_type));
- }
-
- return py_obj;
-}
diff --git a/gi/pygi-marshal-to-py.h b/gi/pygi-marshal-to-py.h
index aa845031..ad80a3bd 100644
--- a/gi/pygi-marshal-to-py.h
+++ b/gi/pygi-marshal-to-py.h
@@ -30,32 +30,5 @@ PyObject *_pygi_marshal_to_py_interface_flags (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_struct_cache_adapter (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_interface(PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_boxed (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-PyObject *_pygi_marshal_to_py_interface_union (PyGIInvokeState *state,
- PyGICallableCache *callable_cache,
- PyGIArgCache *arg_cache,
- GIArgument *arg);
-
-/* Simplified marshalers shared between vfunc/closure and direct function calls. */
-PyObject *_pygi_marshal_to_py_interface_struct (GIArgument *arg,
- GIInterfaceInfo *interface_info,
- GType g_type,
- PyObject *py_type,
- GITransfer transfer,
- gboolean is_allocated,
- gboolean is_foreign);
-
-G_END_DECLS
#endif /* __PYGI_MARSHAL_TO_PY_H__ */
diff --git a/gi/pygi-object.c b/gi/pygi-object.c
index 4ad58b1b..9abfc6b9 100644
--- a/gi/pygi-object.c
+++ b/gi/pygi-object.c
@@ -22,7 +22,7 @@
#include <Python.h>
#include <pyglib-python-compat.h>
-#include "pygi-arg-gobject.h"
+#include "pygi-object.h"
#include "pygi-private.h"
#include "pygparamspec.h"
diff --git a/gi/pygi-struct-marshal.c b/gi/pygi-struct-marshal.c
new file mode 100644
index 00000000..a30f03e3
--- /dev/null
+++ b/gi/pygi-struct-marshal.c
@@ -0,0 +1,516 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * 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.1 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <Python.h>
+#include <pyglib-python-compat.h>
+
+#include "pygi-struct-marshal.h"
+#include "pygi-private.h"
+
+/*
+ * _is_union_member - check to see if the py_arg is actually a member of the
+ * expected C union
+ */
+static gboolean
+_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 (interface_info);
+
+ if (info_type != GI_INFO_TYPE_UNION)
+ return FALSE;
+
+ union_info = (GIUnionInfo *) interface_info;
+ n_fields = g_union_info_get_n_fields (union_info);
+
+ for (i = 0; i < n_fields; i++) {
+ GIFieldInfo *field_info;
+ GITypeInfo *field_type_info;
+
+ field_info = g_union_info_get_field (union_info, i);
+ field_type_info = g_field_info_get_type (field_info);
+
+ /* we can only check if the members are interfaces */
+ if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) {
+ GIInterfaceInfo *field_iface_info;
+ PyObject *py_type;
+
+ field_iface_info = g_type_info_get_interface (field_type_info);
+ py_type = _pygi_type_import_by_gi_info ((GIBaseInfo *) field_iface_info);
+
+ if (py_type != NULL && PyObject_IsInstance (py_arg, py_type)) {
+ is_member = TRUE;
+ }
+
+ Py_XDECREF (py_type);
+ g_base_info_unref ( ( GIBaseInfo *) field_iface_info);
+ }
+
+ g_base_info_unref ( ( GIBaseInfo *) field_type_info);
+ g_base_info_unref ( ( GIBaseInfo *) field_info);
+
+ if (is_member)
+ break;
+ }
+
+ return is_member;
+}
+
+
+/*
+ * GValue from Python
+ */
+
+/* _pygi_marshal_from_py_gvalue:
+ * py_arg: (in):
+ * arg: (out):
+ * transfer:
+ * copy_reference: TRUE if arg should use the pointer reference held by py_arg
+ * when it is already holding a GValue vs. copying the value.
+ */
+gboolean
+_pygi_marshal_from_py_gvalue (PyObject *py_arg,
+ GIArgument *arg,
+ GITransfer transfer,
+ gboolean copy_reference) {
+ 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;
+ }
+
+ /* if already a gvalue, use that, else marshal into gvalue */
+ if (object_type == G_TYPE_VALUE) {
+ GValue *source_value = pyg_boxed_get (py_arg, GValue);
+ if (copy_reference) {
+ value = source_value;
+ } else {
+ value = g_slice_new0 (GValue);
+ g_value_init (value, G_VALUE_TYPE (source_value));
+ g_value_copy (source_value, value);
+ }
+ } else {
+ value = g_slice_new0 (GValue);
+ g_value_init (value, object_type);
+ if (pyg_value_from_pyobject (value, py_arg) < 0) {
+ g_slice_free (GValue, value);
+ PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
+ return FALSE;
+ }
+ }
+
+ arg->v_pointer = value;
+ return TRUE;
+}
+
+void
+_pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* Note py_arg can be NULL for hash table which is a bug. */
+ if (was_processed && py_arg != NULL) {
+ GType py_object_type =
+ pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
+
+ /* When a GValue was not passed, it means the marshalers created a new
+ * one to pass in, clean this up.
+ */
+ if (py_object_type != G_TYPE_VALUE) {
+ g_value_unset ((GValue *) data);
+ g_slice_free (GValue, data);
+ }
+ }
+}
+
+/* _pygi_marshal_from_py_gclosure:
+ * py_arg: (in):
+ * arg: (out):
+ */
+gboolean
+_pygi_marshal_from_py_gclosure(PyObject *py_arg,
+ GIArgument *arg)
+{
+ GClosure *closure;
+ GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE);
+
+ if ( !(PyCallable_Check(py_arg) ||
+ g_type_is_a (object_gtype, G_TYPE_CLOSURE))) {
+ PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
+
+ if (g_type_is_a (object_gtype, G_TYPE_CLOSURE))
+ closure = (GClosure *)pyg_boxed_get (py_arg, void);
+ else
+ closure = pyg_closure_new (py_arg, NULL, NULL);
+
+ if (closure == NULL) {
+ PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
+ return FALSE;
+ }
+
+ arg->v_pointer = closure;
+ return TRUE;
+}
+
+/* _pygi_marshal_from_py_interface_struct:
+ *
+ * Dispatcher to various sub marshalers
+ */
+gboolean
+_pygi_marshal_from_py_interface_struct (PyObject *py_arg,
+ GIArgument *arg,
+ const gchar *arg_name,
+ GIBaseInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean copy_reference,
+ gboolean is_foreign,
+ gboolean is_pointer)
+{
+ gboolean is_union = FALSE;
+
+ 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,
+ copy_reference);
+ } 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 */
+ is_union = _is_union_member (interface_info, py_arg);
+ if (!is_union) {
+ goto type_error;
+ }
+ }
+
+ if (g_type_is_a (g_type, G_TYPE_BOXED)) {
+ /* Additionally use pyg_type_from_object to pull the stashed __gtype__
+ * attribute off of the input argument for type checking. This is needed
+ * to work around type discrepancies in cases with aliased (typedef) types.
+ * e.g. GtkAllocation, GdkRectangle.
+ * See: https://bugzilla.gnomethere are .org/show_bug.cgi?id=707140
+ */
+ if (is_union || pyg_boxed_check (py_arg, g_type) ||
+ g_type_is_a (pyg_type_from_object (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 {
+ goto type_error;
+ }
+
+ } 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) || !is_pointer || 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);
+ if (transfer == GI_TRANSFER_EVERYTHING) {
+ g_variant_ref ((GVariant *)arg->v_pointer);
+ }
+
+ } else {
+ PyErr_Format (PyExc_NotImplementedError,
+ "structure type '%s' is not supported yet",
+ g_type_name(g_type));
+ return FALSE;
+ }
+ return TRUE;
+
+type_error:
+ {
+ 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;
+ }
+}
+
+static gboolean
+_pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+
+ gboolean res = _pygi_marshal_from_py_interface_struct (py_arg,
+ arg,
+ arg_cache->arg_name,
+ iface_cache->interface_info,
+ iface_cache->g_type,
+ iface_cache->py_type,
+ arg_cache->transfer,
+ TRUE, /*copy_reference*/
+ iface_cache->is_foreign,
+ arg_cache->is_pointer);
+
+ /* Assume struct marshaling is always a pointer and assign cleanup_data
+ * here rather than passing it further down the chain.
+ */
+ *cleanup_data = arg->v_pointer;
+ return res;
+}
+
+static void
+_pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (state->failed && was_processed)
+ pygi_struct_foreign_release (
+ ( (PyGIInterfaceCache *)arg_cache)->interface_info,
+ data);
+}
+
+
+PyObject *
+_pygi_marshal_to_py_interface_struct (GIArgument *arg,
+ GIInterfaceInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean is_allocated,
+ gboolean is_foreign)
+{
+ PyObject *py_obj = NULL;
+
+ if (arg->v_pointer == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ if (g_type_is_a (g_type, G_TYPE_VALUE)) {
+ py_obj = pyg_value_as_pyobject (arg->v_pointer, FALSE);
+ } else if (is_foreign) {
+ py_obj = pygi_struct_foreign_convert_from_g_argument (interface_info,
+ arg->v_pointer);
+ } else if (g_type_is_a (g_type, G_TYPE_BOXED)) {
+ if (py_type) {
+ py_obj = _pygi_boxed_new ((PyTypeObject *) py_type,
+ arg->v_pointer,
+ transfer == GI_TRANSFER_EVERYTHING || is_allocated,
+ is_allocated ?
+ g_struct_info_get_size(interface_info) : 0);
+ }
+ } else if (g_type_is_a (g_type, G_TYPE_POINTER)) {
+ if (py_type == NULL ||
+ !PyType_IsSubtype ((PyTypeObject *) py_type, &PyGIStruct_Type)) {
+ g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
+ py_obj = pyg_pointer_new (g_type, arg->v_pointer);
+ } else {
+ py_obj = _pygi_struct_new ( (PyTypeObject *) py_type,
+ arg->v_pointer,
+ transfer == GI_TRANSFER_EVERYTHING);
+ }
+ } else if (g_type_is_a (g_type, G_TYPE_VARIANT)) {
+ /* Note: sink the variant (add a ref) only if we are not transfered ownership.
+ * GLib.Variant overrides __del__ which will then call "g_variant_unref" for
+ * cleanup in either case. */
+ if (py_type) {
+ if (transfer == GI_TRANSFER_NOTHING) {
+ g_variant_ref_sink (arg->v_pointer);
+ }
+ py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
+ arg->v_pointer,
+ FALSE);
+ }
+ } else if (g_type == G_TYPE_NONE) {
+ if (py_type) {
+ py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
+ arg->v_pointer,
+ transfer == GI_TRANSFER_EVERYTHING);
+ }
+ } else {
+ PyErr_Format (PyExc_NotImplementedError,
+ "structure type '%s' is not supported yet",
+ g_type_name (g_type));
+ }
+
+ return py_obj;
+}
+
+static PyObject *
+_pygi_marshal_to_py_interface_struct_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+
+ return _pygi_marshal_to_py_interface_struct (arg,
+ iface_cache->interface_info,
+ iface_cache->g_type,
+ iface_cache->py_type,
+ arg_cache->transfer,
+ arg_cache->is_caller_allocates,
+ iface_cache->is_foreign);
+}
+
+static void
+_pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *dummy,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ pygi_struct_foreign_release (
+ ( (PyGIInterfaceCache *)arg_cache)->interface_info,
+ data);
+}
+
+
+static void
+_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
+ GIInterfaceInfo *iface_info,
+ GITransfer transfer)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
+
+ if (iface_cache->g_type == G_TYPE_VALUE)
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
+ else if (iface_cache->is_foreign)
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
+}
+
+static void
+_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
+ GIInterfaceInfo *iface_info,
+ GITransfer transfer)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
+
+ if (iface_cache->is_foreign)
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
+}
+
+static gboolean
+pygi_arg_struct_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info)
+{
+ /* NOTE: usage of pygi_arg_interface_new_from_info already calls
+ * pygi_arg_interface_setup so no need to do it here.
+ */
+
+ if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+ _arg_cache_from_py_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+ }
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON) {
+ _arg_cache_to_py_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_struct_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info)
+{
+ gboolean res = FALSE;
+ PyGIArgCache *cache = NULL;
+
+ cache = pygi_arg_interface_new_from_info (type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ if (cache == NULL)
+ return NULL;
+
+ res = pygi_arg_struct_setup_from_info (cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ iface_info);
+ if (res) {
+ return cache;
+ } else {
+ _pygi_arg_cache_free (cache);
+ return NULL;
+ }
+}
diff --git a/gi/pygi-struct-marshal.h b/gi/pygi-struct-marshal.h
new file mode 100644
index 00000000..66e3ecfe
--- /dev/null
+++ b/gi/pygi-struct-marshal.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * 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.1 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PYGI_STRUCT_MARSHAL_H__
+#define __PYGI_STRUCT_MARSHAL_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+PyGIArgCache *pygi_arg_struct_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be null */
+ GITransfer transfer,
+ PyGIDirection direction,
+ GIInterfaceInfo *iface_info);
+
+
+gboolean _pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/
+ GIArgument *arg, /*out*/
+ GITransfer transfer,
+ gboolean is_allocated);
+
+
+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,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean is_allocated,
+ gboolean is_foreign,
+ gboolean is_pointer);
+
+PyObject *_pygi_marshal_to_py_interface_struct (GIArgument *arg,
+ GIInterfaceInfo *interface_info,
+ GType g_type,
+ PyObject *py_type,
+ GITransfer transfer,
+ gboolean is_allocated,
+ gboolean is_foreign);
+
+/* Needed for hack in pygi-arg-garray.c */
+void _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed);
+
+G_END_DECLS
+
+#endif /*__PYGI_STRUCT_MARSHAL_H__*/