Imported Upstream version 3.21.91
[platform/upstream/python-gobject.git] / gi / pygi-value.c
1
2 /* -*- Mode: C; c-basic-offset: 4 -*-
3  * vim: tabstop=4 shiftwidth=4 expandtab
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <Python.h>
20 #include "pygi-value.h"
21 #include "pygi-struct.h"
22 #include "pyglib-python-compat.h"
23 #include "pygobject-object.h"
24 #include "pygtype.h"
25 #include "pygenum.h"
26 #include "pygpointer.h"
27 #include "pygboxed.h"
28 #include "pygflags.h"
29 #include "pygparamspec.h"
30
31 GIArgument
32 _pygi_argument_from_g_value(const GValue *value,
33                             GITypeInfo *type_info)
34 {
35     GIArgument arg = { 0, };
36
37     GITypeTag type_tag = g_type_info_get_tag (type_info);
38
39     /* For the long handling: long can be equivalent to
40        int32 or int64, depending on the architecture, but
41        gi doesn't tell us (and same for ulong)
42     */
43     switch (type_tag) {
44         case GI_TYPE_TAG_BOOLEAN:
45             arg.v_boolean = g_value_get_boolean (value);
46             break;
47         case GI_TYPE_TAG_INT8:
48             arg.v_int8 = g_value_get_schar (value);
49             break;
50         case GI_TYPE_TAG_INT16:
51         case GI_TYPE_TAG_INT32:
52             if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
53                 arg.v_int = g_value_get_long (value);
54             else
55                 arg.v_int = g_value_get_int (value);
56             break;
57         case GI_TYPE_TAG_INT64:
58             if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
59                 arg.v_int64 = g_value_get_long (value);
60             else
61                 arg.v_int64 = g_value_get_int64 (value);
62             break;
63         case GI_TYPE_TAG_UINT8:
64             arg.v_uint8 = g_value_get_uchar (value);
65             break;
66         case GI_TYPE_TAG_UINT16:
67         case GI_TYPE_TAG_UINT32:
68             if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
69                 arg.v_uint = g_value_get_ulong (value);
70             else
71                 arg.v_uint = g_value_get_uint (value);
72             break;
73         case GI_TYPE_TAG_UINT64:
74             if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
75                 arg.v_uint64 = g_value_get_ulong (value);
76             else
77                 arg.v_uint64 = g_value_get_uint64 (value);
78             break;
79         case GI_TYPE_TAG_UNICHAR:
80             arg.v_uint32 = g_value_get_schar (value);
81             break;
82         case GI_TYPE_TAG_FLOAT:
83             arg.v_float = g_value_get_float (value);
84             break;
85         case GI_TYPE_TAG_DOUBLE:
86             arg.v_double = g_value_get_double (value);
87             break;
88         case GI_TYPE_TAG_GTYPE:
89             arg.v_long = g_value_get_gtype (value);
90             break;
91         case GI_TYPE_TAG_UTF8:
92         case GI_TYPE_TAG_FILENAME:
93             /* Callers are responsible for ensuring the GValue stays alive
94              * long enough for the string to be copied. */
95             arg.v_string = (char *)g_value_get_string (value);
96             break;
97         case GI_TYPE_TAG_GLIST:
98         case GI_TYPE_TAG_GSLIST:
99         case GI_TYPE_TAG_ARRAY:
100         case GI_TYPE_TAG_GHASH:
101             if (G_VALUE_HOLDS_BOXED (value))
102                 arg.v_pointer = g_value_get_boxed (value);
103             else
104                 /* e. g. GSettings::change-event */
105                 arg.v_pointer = g_value_get_pointer (value);
106             break;
107         case GI_TYPE_TAG_INTERFACE:
108         {
109             GIBaseInfo *info;
110             GIInfoType info_type;
111
112             info = g_type_info_get_interface (type_info);
113             info_type = g_base_info_get_type (info);
114
115             g_base_info_unref (info);
116
117             switch (info_type) {
118                 case GI_INFO_TYPE_FLAGS:
119                     arg.v_uint = g_value_get_flags (value);
120                     break;
121                 case GI_INFO_TYPE_ENUM:
122                     arg.v_int = g_value_get_enum (value);
123                     break;
124                 case GI_INFO_TYPE_INTERFACE:
125                 case GI_INFO_TYPE_OBJECT:
126                     if (G_VALUE_HOLDS_PARAM (value))
127                       arg.v_pointer = g_value_get_param (value);
128                     else
129                       arg.v_pointer = g_value_get_object (value);
130                     break;
131                 case GI_INFO_TYPE_BOXED:
132                 case GI_INFO_TYPE_STRUCT:
133                 case GI_INFO_TYPE_UNION:
134                     if (G_VALUE_HOLDS (value, G_TYPE_BOXED)) {
135                         arg.v_pointer = g_value_get_boxed (value);
136                     } else if (G_VALUE_HOLDS (value, G_TYPE_VARIANT)) {
137                         arg.v_pointer = g_value_get_variant (value);
138                     } else if (G_VALUE_HOLDS (value, G_TYPE_POINTER)) {
139                         arg.v_pointer = g_value_get_pointer (value);
140                     } else {
141                         PyErr_Format (PyExc_NotImplementedError,
142                                       "Converting GValue's of type '%s' is not implemented.",
143                                       g_type_name (G_VALUE_TYPE (value)));
144                     }
145                     break;
146                 default:
147                     PyErr_Format (PyExc_NotImplementedError,
148                                   "Converting GValue's of type '%s' is not implemented.",
149                                   g_info_type_to_string (info_type));
150                     break;
151             }
152             break;
153         }
154         case GI_TYPE_TAG_ERROR:
155             arg.v_pointer = g_value_get_boxed (value);
156             break;
157         case GI_TYPE_TAG_VOID:
158             arg.v_pointer = g_value_get_pointer (value);
159             break;
160     }
161
162     return arg;
163 }
164
165
166 /* Ignore g_value_array deprecations. Although they are deprecated,
167  * we still need to support the marshaling of them in PyGObject.
168  */
169 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
170
171 static int
172 pyg_value_array_from_pyobject(GValue *value,
173                               PyObject *obj,
174                               const GParamSpecValueArray *pspec)
175 {
176     int len;
177     GValueArray *value_array;
178     int i;
179
180     len = PySequence_Length(obj);
181     if (len == -1) {
182         PyErr_Clear();
183         return -1;
184     }
185
186     if (pspec && pspec->fixed_n_elements > 0 && len != pspec->fixed_n_elements)
187         return -1;
188
189     value_array = g_value_array_new(len);
190
191     for (i = 0; i < len; ++i) {
192         PyObject *item = PySequence_GetItem(obj, i);
193         GType type;
194         GValue item_value = { 0, };
195         int status;
196
197         if (! item) {
198             PyErr_Clear();
199             g_value_array_free(value_array);
200             return -1;
201         }
202
203         if (pspec && pspec->element_spec)
204             type = G_PARAM_SPEC_VALUE_TYPE(pspec->element_spec);
205         else if (item == Py_None)
206             type = G_TYPE_POINTER; /* store None as NULL */
207         else {
208             type = pyg_type_from_object((PyObject*)Py_TYPE(item));
209             if (! type) {
210                 PyErr_Clear();
211                 g_value_array_free(value_array);
212                 Py_DECREF(item);
213                 return -1;
214             }
215         }
216
217         g_value_init(&item_value, type);
218         status = (pspec && pspec->element_spec)
219                  ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
220                  : pyg_value_from_pyobject(&item_value, item);
221         Py_DECREF(item);
222
223         if (status == -1) {
224             g_value_array_free(value_array);
225             g_value_unset(&item_value);
226             return -1;
227         }
228
229         g_value_array_append(value_array, &item_value);
230         g_value_unset(&item_value);
231     }
232
233     g_value_take_boxed(value, value_array);
234     return 0;
235 }
236
237 G_GNUC_END_IGNORE_DEPRECATIONS
238
239 static int
240 pyg_array_from_pyobject(GValue *value,
241                         PyObject *obj)
242 {
243     int len;
244     GArray *array;
245     int i;
246
247     len = PySequence_Length(obj);
248     if (len == -1) {
249         PyErr_Clear();
250         return -1;
251     }
252
253     array = g_array_new(FALSE, TRUE, sizeof(GValue));
254
255     for (i = 0; i < len; ++i) {
256         PyObject *item = PySequence_GetItem(obj, i);
257         GType type;
258         GValue item_value = { 0, };
259         int status;
260
261         if (! item) {
262             PyErr_Clear();
263             g_array_free(array, FALSE);
264             return -1;
265         }
266
267         if (item == Py_None)
268             type = G_TYPE_POINTER; /* store None as NULL */
269         else {
270             type = pyg_type_from_object((PyObject*)Py_TYPE(item));
271             if (! type) {
272                 PyErr_Clear();
273                 g_array_free(array, FALSE);
274                 Py_DECREF(item);
275                 return -1;
276             }
277         }
278
279         g_value_init(&item_value, type);
280         status = pyg_value_from_pyobject(&item_value, item);
281         Py_DECREF(item);
282
283         if (status == -1) {
284             g_array_free(array, FALSE);
285             g_value_unset(&item_value);
286             return -1;
287         }
288
289         g_array_append_val(array, item_value);
290     }
291
292     g_value_take_boxed(value, array);
293     return 0;
294 }
295
296 /**
297  * pyg_value_from_pyobject_with_error:
298  * @value: the GValue object to store the converted value in.
299  * @obj: the Python object to convert.
300  *
301  * This function converts a Python object and stores the result in a
302  * GValue.  The GValue must be initialised in advance with
303  * g_value_init().  If the Python object can't be converted to the
304  * type of the GValue, then an error is returned.
305  *
306  * Returns: 0 on success, -1 on error.
307  */
308 int
309 pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
310 {
311     PyObject *tmp;
312     GType value_type = G_VALUE_TYPE(value);
313
314     switch (G_TYPE_FUNDAMENTAL(value_type)) {
315     case G_TYPE_INTERFACE:
316         /* we only handle interface types that have a GObject prereq */
317         if (g_type_is_a(value_type, G_TYPE_OBJECT)) {
318             if (obj == Py_None)
319                 g_value_set_object(value, NULL);
320             else {
321                 if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
322                     PyErr_SetString(PyExc_TypeError, "GObject is required");
323                     return -1;
324                 }
325                 if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
326                         value_type)) {
327                     PyErr_SetString(PyExc_TypeError, "Invalid GObject type for assignment");
328                     return -1;
329                 }
330                 g_value_set_object(value, pygobject_get(obj));
331             }
332         } else {
333             PyErr_SetString(PyExc_TypeError, "Unsupported conversion");
334             return -1;
335         }
336         break;
337     case G_TYPE_CHAR:
338         if (PYGLIB_PyLong_Check(obj)) {
339             glong val;
340             val = PYGLIB_PyLong_AsLong(obj);
341             if (val >= -128 && val <= 127)
342                 g_value_set_schar(value, (gchar) val);
343             else
344                 return -1;
345         }
346 #if PY_VERSION_HEX < 0x03000000
347         else if (PyString_Check(obj)) {
348             g_value_set_schar(value, PyString_AsString(obj)[0]);
349         }
350 #endif
351         else if (PyUnicode_Check(obj)) {
352             tmp = PyUnicode_AsUTF8String(obj);
353             g_value_set_schar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
354             Py_DECREF(tmp);
355         } else {
356             PyErr_SetString(PyExc_TypeError, "Cannot convert to TYPE_CHAR");
357             return -1;
358         }
359
360         break;
361     case G_TYPE_UCHAR:
362         if (PYGLIB_PyLong_Check(obj)) {
363             glong val;
364             val = PYGLIB_PyLong_AsLong(obj);
365             if (val >= 0 && val <= 255)
366                 g_value_set_uchar(value, (guchar) val);
367             else
368                 return -1;
369 #if PY_VERSION_HEX < 0x03000000
370         } else if (PyString_Check(obj)) {
371             g_value_set_uchar(value, PyString_AsString(obj)[0]);
372 #endif
373         } else if (PyUnicode_Check(obj)) {
374             tmp = PyUnicode_AsUTF8String(obj);
375             g_value_set_uchar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
376             Py_DECREF(tmp);
377         } else {
378             PyErr_Clear();
379             return -1;
380         }
381         break;
382     case G_TYPE_BOOLEAN:
383         g_value_set_boolean(value, PyObject_IsTrue(obj));
384         break;
385     case G_TYPE_INT:
386         g_value_set_int(value, PYGLIB_PyLong_AsLong(obj));
387         break;
388     case G_TYPE_UINT:
389     {
390         if (PYGLIB_PyLong_Check(obj)) {
391             gulong val;
392
393             /* check that number is not negative */
394             if (PyLong_AsLongLong(obj) < 0)
395                 return -1;
396
397             val = PyLong_AsUnsignedLong(obj);
398             if (val <= G_MAXUINT)
399                 g_value_set_uint(value, (guint) val);
400             else
401                 return -1;
402         } else {
403             g_value_set_uint(value, PyLong_AsUnsignedLong(obj));
404         }
405     }
406     break;
407     case G_TYPE_LONG:
408         g_value_set_long(value, PYGLIB_PyLong_AsLong(obj));
409         break;
410     case G_TYPE_ULONG:
411 #if PY_VERSION_HEX < 0x03000000
412         if (PyInt_Check(obj)) {
413             long val;
414
415             val = PYGLIB_PyLong_AsLong(obj);
416             if (val < 0) {
417                 PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
418                 return -1;
419             }
420             g_value_set_ulong(value, (gulong)val);
421         } else
422 #endif
423             if (PyLong_Check(obj))
424                 g_value_set_ulong(value, PyLong_AsUnsignedLong(obj));
425             else
426                 return -1;
427         break;
428     case G_TYPE_INT64:
429         g_value_set_int64(value, PyLong_AsLongLong(obj));
430         break;
431     case G_TYPE_UINT64:
432 #if PY_VERSION_HEX < 0x03000000
433         if (PyInt_Check(obj)) {
434             long v = PyInt_AsLong(obj);
435             if (v < 0) {
436                 PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
437                 return -1;
438             }
439             g_value_set_uint64(value, v);
440         } else
441 #endif
442             if (PyLong_Check(obj))
443                 g_value_set_uint64(value, PyLong_AsUnsignedLongLong(obj));
444             else
445                 return -1;
446         break;
447     case G_TYPE_ENUM:
448     {
449         gint val = 0;
450         if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
451             return -1;
452         }
453         g_value_set_enum(value, val);
454     }
455     break;
456     case G_TYPE_FLAGS:
457     {
458         guint val = 0;
459         if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
460             return -1;
461         }
462         g_value_set_flags(value, val);
463     }
464     break;
465     case G_TYPE_FLOAT:
466         g_value_set_float(value, PyFloat_AsDouble(obj));
467         break;
468     case G_TYPE_DOUBLE:
469         g_value_set_double(value, PyFloat_AsDouble(obj));
470         break;
471     case G_TYPE_STRING:
472         if (obj == Py_None) {
473             g_value_set_string(value, NULL);
474         } else {
475             PyObject* tmp_str = PyObject_Str(obj);
476             if (tmp_str == NULL) {
477                 PyErr_Clear();
478                 if (PyUnicode_Check(obj)) {
479                     tmp = PyUnicode_AsUTF8String(obj);
480                     g_value_set_string(value, PYGLIB_PyBytes_AsString(tmp));
481                     Py_DECREF(tmp);
482                 } else {
483                     PyErr_SetString(PyExc_TypeError, "Expected string");
484                     return -1;
485                 }
486             } else {
487 #if PY_VERSION_HEX < 0x03000000
488                 g_value_set_string(value, PyString_AsString(tmp_str));
489 #else
490                 tmp = PyUnicode_AsUTF8String(tmp_str);
491                 g_value_set_string(value, PyBytes_AsString(tmp));
492                 Py_DECREF(tmp);
493 #endif
494             }
495             Py_XDECREF(tmp_str);
496         }
497         break;
498     case G_TYPE_POINTER:
499         if (obj == Py_None)
500             g_value_set_pointer(value, NULL);
501         else if (PyObject_TypeCheck(obj, &PyGPointer_Type) &&
502                 G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype))
503             g_value_set_pointer(value, pyg_pointer_get(obj, gpointer));
504         else if (PYGLIB_CPointer_Check(obj))
505             g_value_set_pointer(value, PYGLIB_CPointer_GetPointer(obj, NULL));
506         else if (G_VALUE_HOLDS_GTYPE (value))
507             g_value_set_gtype (value, pyg_type_from_object (obj));
508         else {
509             PyErr_SetString(PyExc_TypeError, "Expected pointer");
510             return -1;
511         }
512         break;
513     case G_TYPE_BOXED: {
514         PyGTypeMarshal *bm;
515         gboolean holds_value_array;
516
517         G_GNUC_BEGIN_IGNORE_DEPRECATIONS
518         holds_value_array = G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY);
519         G_GNUC_END_IGNORE_DEPRECATIONS
520
521         if (obj == Py_None)
522             g_value_set_boxed(value, NULL);
523         else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
524             g_value_set_boxed(value, obj);
525         else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) &&
526                 G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype))
527             g_value_set_boxed(value, pyg_boxed_get(obj, gpointer));
528         else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
529             GType type;
530             GValue *n_value;
531
532             type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
533             if (G_UNLIKELY (! type)) {
534                 return -1;
535             }
536             n_value = g_new0 (GValue, 1);
537             g_value_init (n_value, type);
538             g_value_take_boxed (value, n_value);
539             return pyg_value_from_pyobject_with_error (n_value, obj);
540         }
541         else if (PySequence_Check(obj) && holds_value_array)
542             return pyg_value_array_from_pyobject(value, obj, NULL);
543
544         else if (PySequence_Check(obj) &&
545                 G_VALUE_HOLDS(value, G_TYPE_ARRAY))
546             return pyg_array_from_pyobject(value, obj);
547         else if (PYGLIB_PyUnicode_Check(obj) &&
548                 G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
549             GString *string;
550             char *buffer;
551             Py_ssize_t len;
552             if (PYGLIB_PyUnicode_AsStringAndSize(obj, &buffer, &len))
553                 return -1;
554             string = g_string_new_len(buffer, len);
555             g_value_set_boxed(value, string);
556             g_string_free (string, TRUE);
557             break;
558         }
559         else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
560             return bm->tovalue(value, obj);
561         else if (PYGLIB_CPointer_Check(obj))
562             g_value_set_boxed(value, PYGLIB_CPointer_GetPointer(obj, NULL));
563         else {
564             PyErr_SetString(PyExc_TypeError, "Expected Boxed");
565             return -1;
566         }
567         break;
568     }
569     case G_TYPE_PARAM:
570         /* we need to support both the wrapped _gobject.GParamSpec and the GI
571          * GObject.ParamSpec */
572         if (G_IS_PARAM_SPEC (pygobject_get (obj)))
573             g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
574         else if (pyg_param_spec_check (obj))
575             g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL));
576         else {
577             PyErr_SetString(PyExc_TypeError, "Expected ParamSpec");
578             return -1;
579         }
580         break;
581     case G_TYPE_OBJECT:
582         if (obj == Py_None) {
583             g_value_set_object(value, NULL);
584         } else if (PyObject_TypeCheck(obj, &PyGObject_Type) &&
585                 G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
586                         G_VALUE_TYPE(value))) {
587             g_value_set_object(value, pygobject_get(obj));
588         } else {
589             PyErr_SetString(PyExc_TypeError, "Expected GObject");
590             return -1;
591         }
592         break;
593     case G_TYPE_VARIANT:
594     {
595         if (obj == Py_None)
596             g_value_set_variant(value, NULL);
597         else if (pyg_type_from_object_strict(obj, FALSE) == G_TYPE_VARIANT)
598             g_value_set_variant(value, pyg_boxed_get(obj, GVariant));
599         else {
600             PyErr_SetString(PyExc_TypeError, "Expected Variant");
601             return -1;
602         }
603         break;
604     }
605     default:
606     {
607         PyGTypeMarshal *bm;
608         if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) {
609             return bm->tovalue(value, obj);
610         } else {
611             PyErr_SetString(PyExc_TypeError, "Unknown value type");
612             return -1;
613         }
614         break;
615     }
616     }
617
618     /* If an error occurred, unset the GValue but don't clear the Python error. */
619     if (PyErr_Occurred()) {
620         g_value_unset(value);
621         return -1;
622     }
623
624     return 0;
625 }
626
627 /**
628  * pyg_value_from_pyobject:
629  * @value: the GValue object to store the converted value in.
630  * @obj: the Python object to convert.
631  *
632  * Same basic function as pyg_value_from_pyobject_with_error but clears
633  * any Python errors before returning.
634  *
635  * Returns: 0 on success, -1 on error.
636  */
637 int
638 pyg_value_from_pyobject(GValue *value, PyObject *obj)
639 {
640     int res = pyg_value_from_pyobject_with_error (value, obj);
641
642     if (PyErr_Occurred()) {
643         PyErr_Clear();
644         return -1;
645     }
646     return res;
647 }
648
649 /**
650  * pygi_value_to_py_basic_type:
651  * @value: the GValue object.
652  *
653  * This function creates/returns a Python wrapper object that
654  * represents the GValue passed as an argument limited to supporting basic types
655  * like ints, bools, and strings.
656  *
657  * Returns: a PyObject representing the value.
658  */
659 PyObject *
660 pygi_value_to_py_basic_type (const GValue *value, GType fundamental)
661 {
662     switch (fundamental) {
663     case G_TYPE_CHAR:
664         return PYGLIB_PyLong_FromLong (g_value_get_schar (value));
665
666     case G_TYPE_UCHAR:
667         return PYGLIB_PyLong_FromLong (g_value_get_uchar (value));
668
669     case G_TYPE_BOOLEAN: {
670         return PyBool_FromLong(g_value_get_boolean(value));
671     }
672     case G_TYPE_INT:
673         return PYGLIB_PyLong_FromLong(g_value_get_int(value));
674     case G_TYPE_UINT:
675     {
676         /* in Python, the Int object is backed by a long.  If a
677                long can hold the whole value of an unsigned int, use
678                an Int.  Otherwise, use a Long object to avoid overflow.
679                This matches the ULongArg behavior in codegen/argtypes.h */
680 #if (G_MAXUINT <= G_MAXLONG)
681         return PYGLIB_PyLong_FromLong((glong) g_value_get_uint(value));
682 #else
683         return PyLong_FromUnsignedLong((gulong) g_value_get_uint(value));
684 #endif
685     }
686     case G_TYPE_LONG:
687         return PYGLIB_PyLong_FromLong(g_value_get_long(value));
688     case G_TYPE_ULONG:
689     {
690         gulong val = g_value_get_ulong(value);
691
692         if (val <= G_MAXLONG)
693             return PYGLIB_PyLong_FromLong((glong) val);
694         else
695             return PyLong_FromUnsignedLong(val);
696     }
697     case G_TYPE_INT64:
698     {
699         gint64 val = g_value_get_int64(value);
700
701         if (G_MINLONG <= val && val <= G_MAXLONG)
702             return PYGLIB_PyLong_FromLong((glong) val);
703         else
704             return PyLong_FromLongLong(val);
705     }
706     case G_TYPE_UINT64:
707     {
708         guint64 val = g_value_get_uint64(value);
709
710         if (val <= G_MAXLONG)
711             return PYGLIB_PyLong_FromLong((glong) val);
712         else
713             return PyLong_FromUnsignedLongLong(val);
714     }
715     case G_TYPE_ENUM:
716         return pyg_enum_from_gtype(G_VALUE_TYPE(value), g_value_get_enum(value));
717     case G_TYPE_FLAGS:
718         return pyg_flags_from_gtype(G_VALUE_TYPE(value), g_value_get_flags(value));
719     case G_TYPE_FLOAT:
720         return PyFloat_FromDouble(g_value_get_float(value));
721     case G_TYPE_DOUBLE:
722         return PyFloat_FromDouble(g_value_get_double(value));
723     case G_TYPE_STRING:
724     {
725         const gchar *str = g_value_get_string(value);
726
727         if (str)
728             return PYGLIB_PyUnicode_FromString(str);
729         Py_INCREF(Py_None);
730         return Py_None;
731     }
732     default:
733         return NULL;
734     }
735 }
736
737 /**
738  * pygi_value_to_py_structured_type:
739  * @value: the GValue object.
740  * @copy_boxed: true if boxed values should be copied.
741  *
742  * This function creates/returns a Python wrapper object that
743  * represents the GValue passed as an argument.
744  *
745  * Returns: a PyObject representing the value.
746  */
747 PyObject *
748 pygi_value_to_py_structured_type (const GValue *value, GType fundamental, gboolean copy_boxed)
749 {
750     switch (fundamental) {
751     case G_TYPE_INTERFACE:
752         if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT))
753             return pygobject_new(g_value_get_object(value));
754         else
755             break;
756
757     case G_TYPE_POINTER:
758         if (G_VALUE_HOLDS_GTYPE (value))
759             return pyg_type_wrapper_new (g_value_get_gtype (value));
760         else
761             return pyg_pointer_new(G_VALUE_TYPE(value),
762                     g_value_get_pointer(value));
763     case G_TYPE_BOXED: {
764         PyGTypeMarshal *bm;
765         gboolean holds_value_array;
766
767         G_GNUC_BEGIN_IGNORE_DEPRECATIONS
768         holds_value_array = G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY);
769         G_GNUC_END_IGNORE_DEPRECATIONS
770
771         if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) {
772             PyObject *ret = (PyObject *)g_value_dup_boxed(value);
773             if (ret == NULL) {
774                 Py_INCREF(Py_None);
775                 return Py_None;
776             }
777             return ret;
778         } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
779             GValue *n_value = g_value_get_boxed (value);
780             return pyg_value_as_pyobject(n_value, copy_boxed);
781         } else if (holds_value_array) {
782             GValueArray *array = (GValueArray *) g_value_get_boxed(value);
783             Py_ssize_t n_values = array ? array->n_values : 0;
784             PyObject *ret = PyList_New(n_values);
785             int i;
786             for (i = 0; i < n_values; ++i)
787                 PyList_SET_ITEM(ret, i, pyg_value_as_pyobject
788                         (array->values + i, copy_boxed));
789             return ret;
790         } else if (G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
791             GString *string = (GString *) g_value_get_boxed(value);
792             PyObject *ret = PYGLIB_PyUnicode_FromStringAndSize(string->str, string->len);
793             return ret;
794         }
795         bm = pyg_type_lookup(G_VALUE_TYPE(value));
796         if (bm) {
797             return bm->fromvalue(value);
798         } else {
799             if (copy_boxed)
800                 return pyg_boxed_new(G_VALUE_TYPE(value),
801                         g_value_get_boxed(value), TRUE, TRUE);
802             else
803                 return pyg_boxed_new(G_VALUE_TYPE(value),
804                         g_value_get_boxed(value),FALSE,FALSE);
805         }
806     }
807     case G_TYPE_PARAM:
808         return pyg_param_spec_new(g_value_get_param(value));
809     case G_TYPE_OBJECT:
810         return pygobject_new(g_value_get_object(value));
811     case G_TYPE_VARIANT:
812     {
813         GVariant *v = g_value_get_variant(value);
814         if (v == NULL) {
815             Py_INCREF(Py_None);
816             return Py_None;
817         }
818         return _pygi_struct_new_from_g_type (G_TYPE_VARIANT, g_variant_ref(v), FALSE);
819     }
820     default:
821     {
822         PyGTypeMarshal *bm;
823         if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))))
824             return bm->fromvalue(value);
825         break;
826     }
827     }
828
829     return NULL;
830 }
831
832
833 /**
834  * pyg_value_as_pyobject:
835  * @value: the GValue object.
836  * @copy_boxed: true if boxed values should be copied.
837  *
838  * This function creates/returns a Python wrapper object that
839  * represents the GValue passed as an argument.
840  *
841  * Returns: a PyObject representing the value or %NULL and sets an exception.
842  */
843 PyObject *
844 pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed)
845 {
846     PyObject *pyobj;
847     const gchar *type_name;
848     GType fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value));
849
850     /* HACK: special case char and uchar to return PyBytes intstead of integers
851      * in the general case. Property access will skip this by calling
852      * pygi_value_to_py_basic_type() directly.
853      * See: https://bugzilla.gnome.org/show_bug.cgi?id=733893 */
854     if (fundamental == G_TYPE_CHAR) {
855         gint8 val = g_value_get_schar(value);
856         return PYGLIB_PyUnicode_FromStringAndSize ((char *)&val, 1);
857     } else if (fundamental == G_TYPE_UCHAR) {
858         guint8 val = g_value_get_uchar(value);
859         return PYGLIB_PyBytes_FromStringAndSize ((char *)&val, 1);
860     }
861
862     pyobj = pygi_value_to_py_basic_type (value, fundamental);
863     if (pyobj) {
864         return pyobj;
865     }
866
867     pyobj = pygi_value_to_py_structured_type (value, fundamental, copy_boxed);
868     if (pyobj) {
869         return pyobj;
870     }
871
872     if (!PyErr_Occurred ()) {
873         type_name = g_type_name (G_VALUE_TYPE (value));
874         if (type_name == NULL) {
875             type_name = "(null)";
876         }
877         PyErr_Format (PyExc_TypeError, "unknown type %s", type_name);
878     }
879
880     return NULL;
881
882 }
883
884
885 int
886 pyg_param_gvalue_from_pyobject(GValue* value,
887                                PyObject* py_obj,
888                                const GParamSpec* pspec)
889 {
890     if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
891         gunichar u;
892
893         if (!pyg_pyobj_to_unichar_conv(py_obj, &u)) {
894             PyErr_Clear();
895             return -1;
896         }
897         g_value_set_uint(value, u);
898         return 0;
899     }
900     else if (G_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
901         return pyg_value_array_from_pyobject(value, py_obj,
902                                              G_PARAM_SPEC_VALUE_ARRAY(pspec));
903     else {
904         return pyg_value_from_pyobject(value, py_obj);
905     }
906 }
907
908 PyObject*
909 pyg_param_gvalue_as_pyobject(const GValue* gvalue,
910                              gboolean copy_boxed,
911                              const GParamSpec* pspec)
912 {
913     if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
914         gunichar u;
915         Py_UNICODE uni_buffer[2] = { 0, 0 };
916
917         u = g_value_get_uint(gvalue);
918         uni_buffer[0] = u;
919         return PyUnicode_FromUnicode(uni_buffer, 1);
920     }
921     else {
922         return pyg_value_as_pyobject(gvalue, copy_boxed);
923     }
924 }
925
926 PyObject *
927 pyg_strv_from_gvalue(const GValue *value)
928 {
929     gchar    **argv = (gchar **) g_value_get_boxed(value);
930     int        argc = 0, i;
931     PyObject  *py_argv;
932
933     if (argv) {
934         while (argv[argc])
935             argc++;
936     }
937     py_argv = PyList_New(argc);
938     for (i = 0; i < argc; ++i)
939         PyList_SET_ITEM(py_argv, i, PYGLIB_PyUnicode_FromString(argv[i]));
940     return py_argv;
941 }
942
943 int
944 pyg_strv_to_gvalue(GValue *value, PyObject *obj)
945 {
946     Py_ssize_t argc, i;
947     gchar **argv;
948
949     if (!(PyTuple_Check (obj) || PyList_Check (obj)))
950         return -1;
951
952     argc = PySequence_Length (obj);
953     argv = g_new (gchar *, argc + 1);
954     for (i = 0; i < argc; ++i) {
955         PyObject* item = PySequence_Fast_GET_ITEM (obj, i);
956         /* same as _pygi_marshal_from_py_utf8 */
957         if (PyUnicode_Check (item)) {
958             PyObject *pystr_obj = PyUnicode_AsUTF8String (item);
959             if (!pystr_obj) {
960                 goto error;
961             }
962             argv[i] = g_strdup (PYGLIB_PyBytes_AsString (pystr_obj));
963             Py_DECREF (pystr_obj);
964         }
965 #if PY_VERSION_HEX < 0x03000000
966         else if (PyString_Check (item)) {
967             argv[i] = g_strdup (PyString_AsString (item));
968         }
969 #endif
970         else {
971             goto error;
972         }
973     }
974
975     argv[i] = NULL;
976     g_value_take_boxed (value, argv);
977     return 0;
978
979 error:
980     for (i = i - 1; i >= 0; i--) {
981         g_free (argv[i]);
982     }
983     g_free (argv);
984     return -1;
985 }