Add gitlab CI tests
[pygobject.git] / gi / pygi-struct-marshal.c
blob60d2585a5ee65cd2a09656c06cddab08bda13d7d
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
5 * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include <Python.h>
22 #include <glib.h>
23 #include <pyglib-python-compat.h>
25 #include "pygi-struct-marshal.h"
26 #include "pygi-struct.h"
27 #include "pygi-foreign.h"
28 #include "pygi-value.h"
29 #include "pygi-type.h"
30 #include "pygi-boxed.h"
31 #include "pygi-info.h"
32 #include "pygpointer.h"
33 #include "pygboxed.h"
34 #include "pygtype.h"
37 * _is_union_member - check to see if the py_arg is actually a member of the
38 * expected C union
40 static gboolean
41 _is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) {
42 gint i;
43 gint n_fields;
44 GIUnionInfo *union_info;
45 GIInfoType info_type;
46 gboolean is_member = FALSE;
48 info_type = g_base_info_get_type (interface_info);
50 if (info_type != GI_INFO_TYPE_UNION)
51 return FALSE;
53 union_info = (GIUnionInfo *) interface_info;
54 n_fields = g_union_info_get_n_fields (union_info);
56 for (i = 0; i < n_fields; i++) {
57 GIFieldInfo *field_info;
58 GITypeInfo *field_type_info;
60 field_info = g_union_info_get_field (union_info, i);
61 field_type_info = g_field_info_get_type (field_info);
63 /* we can only check if the members are interfaces */
64 if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) {
65 GIInterfaceInfo *field_iface_info;
66 PyObject *py_type;
68 field_iface_info = g_type_info_get_interface (field_type_info);
69 py_type = _pygi_type_import_by_gi_info ((GIBaseInfo *) field_iface_info);
71 if (py_type != NULL && PyObject_IsInstance (py_arg, py_type)) {
72 is_member = TRUE;
75 Py_XDECREF (py_type);
76 g_base_info_unref ( ( GIBaseInfo *) field_iface_info);
79 g_base_info_unref ( ( GIBaseInfo *) field_type_info);
80 g_base_info_unref ( ( GIBaseInfo *) field_info);
82 if (is_member)
83 break;
86 return is_member;
91 * GValue from Python
94 /* pygi_arg_gvalue_from_py_marshal:
95 * py_arg: (in):
96 * arg: (out):
97 * transfer:
98 * copy_reference: TRUE if arg should use the pointer reference held by py_arg
99 * when it is already holding a GValue vs. copying the value.
101 gboolean
102 pygi_arg_gvalue_from_py_marshal (PyObject *py_arg,
103 GIArgument *arg,
104 GITransfer transfer,
105 gboolean copy_reference) {
106 GValue *value;
107 GType object_type;
109 object_type = pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
110 if (object_type == G_TYPE_INVALID) {
111 PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
112 return FALSE;
115 /* if already a gvalue, use that, else marshal into gvalue */
116 if (object_type == G_TYPE_VALUE) {
117 GValue *source_value = pyg_boxed_get (py_arg, GValue);
118 if (copy_reference) {
119 value = source_value;
120 } else {
121 value = g_slice_new0 (GValue);
122 g_value_init (value, G_VALUE_TYPE (source_value));
123 g_value_copy (source_value, value);
125 } else {
126 value = g_slice_new0 (GValue);
127 g_value_init (value, object_type);
128 if (pyg_value_from_pyobject_with_error (value, py_arg) < 0) {
129 g_slice_free (GValue, value);
130 return FALSE;
134 arg->v_pointer = value;
135 return TRUE;
138 void
139 pygi_arg_gvalue_from_py_cleanup (PyGIInvokeState *state,
140 PyGIArgCache *arg_cache,
141 PyObject *py_arg,
142 gpointer data,
143 gboolean was_processed)
145 /* Note py_arg can be NULL for hash table which is a bug. */
146 if (was_processed && py_arg != NULL) {
147 GType py_object_type =
148 pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
150 /* When a GValue was not passed, it means the marshalers created a new
151 * one to pass in, clean this up.
153 if (py_object_type != G_TYPE_VALUE) {
154 g_value_unset ((GValue *) data);
155 g_slice_free (GValue, data);
160 /* pygi_arg_gclosure_from_py_marshal:
161 * py_arg: (in):
162 * arg: (out):
164 static gboolean
165 pygi_arg_gclosure_from_py_marshal (PyObject *py_arg,
166 GIArgument *arg,
167 GITransfer transfer)
169 GClosure *closure;
170 GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE);
172 if ( !(PyCallable_Check(py_arg) ||
173 g_type_is_a (object_gtype, G_TYPE_CLOSURE))) {
174 PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
175 py_arg->ob_type->tp_name);
176 return FALSE;
179 if (g_type_is_a (object_gtype, G_TYPE_CLOSURE)) {
180 closure = (GClosure *)pyg_boxed_get (py_arg, void);
181 /* Make sure we own a ref which is held until cleanup. */
182 if (closure != NULL) {
183 g_closure_ref (closure);
185 } else {
186 closure = pyg_closure_new (py_arg, NULL, NULL);
187 g_closure_ref (closure);
188 g_closure_sink (closure);
191 if (closure == NULL) {
192 PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
193 return FALSE;
196 /* Add an additional ref when transfering everything to the callee. */
197 if (transfer == GI_TRANSFER_EVERYTHING) {
198 g_closure_ref (closure);
201 arg->v_pointer = closure;
202 return TRUE;
205 static void
206 arg_gclosure_from_py_cleanup (PyGIInvokeState *state,
207 PyGIArgCache *arg_cache,
208 PyObject *py_arg,
209 gpointer cleanup_data,
210 gboolean was_processed)
212 if (cleanup_data != NULL) {
213 g_closure_unref (cleanup_data);
217 /* pygi_arg_struct_from_py_marshal:
219 * Dispatcher to various sub marshalers
221 gboolean
222 pygi_arg_struct_from_py_marshal (PyObject *py_arg,
223 GIArgument *arg,
224 const gchar *arg_name,
225 GIBaseInfo *interface_info,
226 GType g_type,
227 PyObject *py_type,
228 GITransfer transfer,
229 gboolean copy_reference,
230 gboolean is_foreign,
231 gboolean is_pointer)
233 gboolean is_union = FALSE;
235 if (py_arg == Py_None) {
236 arg->v_pointer = NULL;
237 return TRUE;
240 /* FIXME: handle this large if statement in the cache
241 * and set the correct marshaller
244 if (g_type_is_a (g_type, G_TYPE_CLOSURE)) {
245 return pygi_arg_gclosure_from_py_marshal (py_arg, arg, transfer);
246 } else if (g_type_is_a (g_type, G_TYPE_VALUE)) {
247 return pygi_arg_gvalue_from_py_marshal(py_arg,
248 arg,
249 transfer,
250 copy_reference);
251 } else if (is_foreign) {
252 PyObject *success;
253 success = pygi_struct_foreign_convert_to_g_argument (py_arg,
254 interface_info,
255 transfer,
256 arg);
258 return (success == Py_None);
259 } else if (!PyObject_IsInstance (py_arg, py_type)) {
260 /* first check to see if this is a member of the expected union */
261 is_union = _is_union_member (interface_info, py_arg);
262 if (!is_union) {
263 goto type_error;
267 if (g_type_is_a (g_type, G_TYPE_BOXED)) {
268 /* Additionally use pyg_type_from_object to pull the stashed __gtype__
269 * attribute off of the input argument for type checking. This is needed
270 * to work around type discrepancies in cases with aliased (typedef) types.
271 * e.g. GtkAllocation, GdkRectangle.
272 * See: https://bugzilla.gnomethere are .org/show_bug.cgi?id=707140
274 if (is_union || pyg_boxed_check (py_arg, g_type) ||
275 g_type_is_a (pyg_type_from_object (py_arg), g_type)) {
276 arg->v_pointer = pyg_boxed_get (py_arg, void);
277 if (transfer == GI_TRANSFER_EVERYTHING) {
278 arg->v_pointer = g_boxed_copy (g_type, arg->v_pointer);
280 } else {
281 goto type_error;
284 } else if (g_type_is_a (g_type, G_TYPE_POINTER) ||
285 g_type_is_a (g_type, G_TYPE_VARIANT) ||
286 g_type == G_TYPE_NONE) {
287 g_warn_if_fail (g_type_is_a (g_type, G_TYPE_VARIANT) || !is_pointer || transfer == GI_TRANSFER_NOTHING);
289 if (g_type_is_a (g_type, G_TYPE_VARIANT) &&
290 pyg_type_from_object (py_arg) != G_TYPE_VARIANT) {
291 PyErr_SetString (PyExc_TypeError, "expected GLib.Variant");
292 return FALSE;
294 arg->v_pointer = pyg_pointer_get (py_arg, void);
295 if (transfer == GI_TRANSFER_EVERYTHING) {
296 g_variant_ref ((GVariant *)arg->v_pointer);
299 } else {
300 PyErr_Format (PyExc_NotImplementedError,
301 "structure type '%s' is not supported yet",
302 g_type_name(g_type));
303 return FALSE;
305 return TRUE;
307 type_error:
309 gchar *type_name = _pygi_g_base_info_get_fullname (interface_info);
310 PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
312 PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
313 arg_name ? arg_name : "self",
314 type_name,
315 module ? PYGLIB_PyUnicode_AsString(module) : "",
316 module ? "." : "",
317 py_arg->ob_type->tp_name);
318 if (module)
319 Py_DECREF (module);
320 g_free (type_name);
321 return FALSE;
325 static gboolean
326 arg_struct_from_py_marshal_adapter (PyGIInvokeState *state,
327 PyGICallableCache *callable_cache,
328 PyGIArgCache *arg_cache,
329 PyObject *py_arg,
330 GIArgument *arg,
331 gpointer *cleanup_data)
333 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
335 gboolean res = pygi_arg_struct_from_py_marshal (py_arg,
336 arg,
337 arg_cache->arg_name,
338 iface_cache->interface_info,
339 iface_cache->g_type,
340 iface_cache->py_type,
341 arg_cache->transfer,
342 TRUE, /*copy_reference*/
343 iface_cache->is_foreign,
344 arg_cache->is_pointer);
346 /* Assume struct marshaling is always a pointer and assign cleanup_data
347 * here rather than passing it further down the chain.
349 *cleanup_data = arg->v_pointer;
350 return res;
353 static void
354 arg_foreign_from_py_cleanup (PyGIInvokeState *state,
355 PyGIArgCache *arg_cache,
356 PyObject *py_arg,
357 gpointer data,
358 gboolean was_processed)
360 if (state->failed && was_processed) {
361 pygi_struct_foreign_release (
362 ( (PyGIInterfaceCache *)arg_cache)->interface_info,
363 data);
368 PyObject *
369 pygi_arg_struct_to_py_marshal (GIArgument *arg,
370 GIInterfaceInfo *interface_info,
371 GType g_type,
372 PyObject *py_type,
373 GITransfer transfer,
374 gboolean is_allocated,
375 gboolean is_foreign)
377 PyObject *py_obj = NULL;
379 if (arg->v_pointer == NULL) {
380 Py_RETURN_NONE;
383 if (g_type_is_a (g_type, G_TYPE_VALUE)) {
384 py_obj = pyg_value_as_pyobject (arg->v_pointer, FALSE);
385 } else if (is_foreign) {
386 py_obj = pygi_struct_foreign_convert_from_g_argument (interface_info,
387 transfer,
388 arg->v_pointer);
389 } else if (g_type_is_a (g_type, G_TYPE_BOXED)) {
390 if (py_type) {
391 /* Force a boxed copy if we are not transfered ownership and the
392 * memory is not caller allocated. */
393 py_obj = _pygi_boxed_new ((PyTypeObject *) py_type,
394 arg->v_pointer,
395 transfer == GI_TRANSFER_NOTHING && !is_allocated,
396 is_allocated ?
397 g_struct_info_get_size(interface_info) : 0);
399 } else if (g_type_is_a (g_type, G_TYPE_POINTER)) {
400 if (py_type == NULL ||
401 !PyType_IsSubtype ((PyTypeObject *) py_type, &PyGIStruct_Type)) {
402 g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
403 py_obj = pyg_pointer_new (g_type, arg->v_pointer);
404 } else {
405 py_obj = _pygi_struct_new ( (PyTypeObject *) py_type,
406 arg->v_pointer,
407 transfer == GI_TRANSFER_EVERYTHING);
409 } else if (g_type_is_a (g_type, G_TYPE_VARIANT)) {
410 /* Note: sink the variant (add a ref) only if we are not transfered ownership.
411 * GLib.Variant overrides __del__ which will then call "g_variant_unref" for
412 * cleanup in either case. */
413 if (py_type) {
414 if (transfer == GI_TRANSFER_NOTHING) {
415 g_variant_ref_sink (arg->v_pointer);
417 py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
418 arg->v_pointer,
419 FALSE);
421 } else if (g_type == G_TYPE_NONE) {
422 if (py_type) {
423 py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
424 arg->v_pointer,
425 transfer == GI_TRANSFER_EVERYTHING || is_allocated);
427 } else {
428 PyErr_Format (PyExc_NotImplementedError,
429 "structure type '%s' is not supported yet",
430 g_type_name (g_type));
433 return py_obj;
436 static PyObject *
437 arg_struct_to_py_marshal_adapter (PyGIInvokeState *state,
438 PyGICallableCache *callable_cache,
439 PyGIArgCache *arg_cache,
440 GIArgument *arg)
442 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
444 return pygi_arg_struct_to_py_marshal (arg,
445 iface_cache->interface_info,
446 iface_cache->g_type,
447 iface_cache->py_type,
448 arg_cache->transfer,
449 arg_cache->is_caller_allocates,
450 iface_cache->is_foreign);
453 static PyObject *
454 arg_boxed_to_py_marshal_pass_by_ref (PyGIInvokeState *state,
455 PyGICallableCache *callable_cache,
456 PyGIArgCache *arg_cache,
457 GIArgument *arg)
459 PyObject *py_obj = NULL;
460 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
462 if (arg->v_pointer == NULL) {
463 Py_RETURN_NONE;
466 if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
467 if (iface_cache->py_type) {
468 py_obj = _pygi_boxed_new ((PyTypeObject *) iface_cache->py_type,
469 arg->v_pointer,
470 FALSE, /* copy_boxed */
471 0); /* slice_alloc */
472 ((PyGBoxed *)py_obj)->free_on_dealloc = FALSE;
474 } else {
475 PyErr_Format (PyExc_NotImplementedError,
476 "expected boxed type but got %s",
477 g_type_name (iface_cache->g_type));
480 return py_obj;
483 static void
484 arg_foreign_to_py_cleanup (PyGIInvokeState *state,
485 PyGIArgCache *arg_cache,
486 PyObject *dummy,
487 gpointer data,
488 gboolean was_processed)
490 if (!was_processed && arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
491 pygi_struct_foreign_release (
492 ( (PyGIInterfaceCache *)arg_cache)->interface_info,
493 data);
497 static gboolean
498 arg_type_class_from_py_marshal (PyGIInvokeState *state,
499 PyGICallableCache *callable_cache,
500 PyGIArgCache *arg_cache,
501 PyObject *py_arg,
502 GIArgument *arg,
503 gpointer *cleanup_data)
505 GType gtype = pyg_type_from_object (py_arg);
507 if (G_TYPE_IS_CLASSED (gtype)) {
508 arg->v_pointer = g_type_class_ref (gtype);
509 *cleanup_data = arg->v_pointer;
510 return TRUE;
511 } else {
512 PyErr_Format (PyExc_TypeError,
513 "Unable to retrieve a GObject type class from \"%s\".",
514 Py_TYPE(py_arg)->tp_name);
515 return FALSE;
519 static void
520 arg_type_class_from_py_cleanup (PyGIInvokeState *state,
521 PyGIArgCache *arg_cache,
522 PyObject *py_arg,
523 gpointer data,
524 gboolean was_processed)
526 if (was_processed) {
527 g_type_class_unref (data);
531 static void
532 arg_struct_from_py_setup (PyGIArgCache *arg_cache,
533 GIInterfaceInfo *iface_info,
534 GITransfer transfer)
536 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
538 if (g_struct_info_is_gtype_struct ((GIStructInfo*)iface_info)) {
539 arg_cache->from_py_marshaller = arg_type_class_from_py_marshal;
540 /* Since we always add a ref in the marshalling, only unref the
541 * GTypeClass when we don't transfer ownership. */
542 if (transfer == GI_TRANSFER_NOTHING) {
543 arg_cache->from_py_cleanup = arg_type_class_from_py_cleanup;
546 } else {
547 arg_cache->from_py_marshaller = arg_struct_from_py_marshal_adapter;
549 if (g_type_is_a (iface_cache->g_type, G_TYPE_CLOSURE)) {
550 arg_cache->from_py_cleanup = arg_gclosure_from_py_cleanup;
552 } else if (iface_cache->g_type == G_TYPE_VALUE) {
553 arg_cache->from_py_cleanup = pygi_arg_gvalue_from_py_cleanup;
555 } else if (iface_cache->is_foreign) {
556 arg_cache->from_py_cleanup = arg_foreign_from_py_cleanup;
561 static void
562 arg_struct_to_py_setup (PyGIArgCache *arg_cache,
563 GIInterfaceInfo *iface_info,
564 GITransfer transfer,
565 GIArgInfo *arg_info)
567 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
569 /* HACK to force GtkTreeModel:iter_next() and iter_previous() vfunc implementations
570 * to receive their Gtk.TreeIter argument as pass-by-reference. We create a new
571 * PyGIBoxed wrapper which does not copy the memory and also does not free it.
572 * This is needed to hack the noted vfunc implementations so they can continue
573 * working with bug https://bugzilla.gnome.org/show_bug.cgi?id=722899
574 * being fixed. This hack should be removed once GTK+ has fixed bug
575 * https://bugzilla.gnome.org/show_bug.cgi?id=734465
576 * and we've moved to a new major version.
578 if (arg_info && g_strcmp0 (iface_cache->type_name, "Gtk.TreeIter") == 0) {
580 /* GICallbackInfo */
581 GIBaseInfo *info = g_base_info_get_container (arg_info);
582 if (info && g_base_info_get_type (info) == GI_INFO_TYPE_CALLBACK &&
583 (g_strcmp0 (g_base_info_get_name (info), "iter_next") == 0 ||
584 g_strcmp0 (g_base_info_get_name (info), "iter_previous") == 0)) {
586 /* GITypeInfo */
587 info = g_base_info_get_container (info);
588 if (info && g_base_info_get_type (info) == GI_INFO_TYPE_TYPE &&
589 g_type_info_get_tag ((GITypeInfo *)info) == GI_TYPE_TAG_INTERFACE) {
591 /* GIFieldInfo */
592 info = g_base_info_get_container (info);
593 if (info && g_base_info_get_type (info) == GI_INFO_TYPE_FIELD) {
595 /* GIStructInfo */
596 info = g_base_info_get_container (info);
597 if (info && g_base_info_get_type (info) == GI_INFO_TYPE_STRUCT &&
598 g_strcmp0 (g_base_info_get_name (info), "TreeModelIface") == 0) {
599 arg_cache->to_py_marshaller = arg_boxed_to_py_marshal_pass_by_ref;
606 if (arg_cache->to_py_marshaller == NULL) {
607 arg_cache->to_py_marshaller = arg_struct_to_py_marshal_adapter;
610 if (iface_cache->is_foreign)
611 arg_cache->to_py_cleanup = arg_foreign_to_py_cleanup;
614 PyGIArgCache *
615 pygi_arg_struct_new_from_info (GITypeInfo *type_info,
616 GIArgInfo *arg_info,
617 GITransfer transfer,
618 PyGIDirection direction,
619 GIInterfaceInfo *iface_info)
621 PyGIArgCache *cache = NULL;
622 PyGIInterfaceCache *iface_cache;
624 cache = pygi_arg_interface_new_from_info (type_info,
625 arg_info,
626 transfer,
627 direction,
628 iface_info);
629 if (cache == NULL)
630 return NULL;
632 iface_cache = (PyGIInterfaceCache *)cache;
633 iface_cache->is_foreign = (g_base_info_get_type ((GIBaseInfo *) iface_info) == GI_INFO_TYPE_STRUCT) &&
634 (g_struct_info_is_foreign ((GIStructInfo*) iface_info));
636 if (direction & PYGI_DIRECTION_FROM_PYTHON) {
637 arg_struct_from_py_setup (cache, iface_info, transfer);
640 if (direction & PYGI_DIRECTION_TO_PYTHON) {
641 arg_struct_to_py_setup (cache, iface_info, transfer, arg_info);
644 return cache;