summaryrefslogtreecommitdiff
path: root/gi/pygi-value.c
diff options
context:
space:
mode:
Diffstat (limited to 'gi/pygi-value.c')
-rw-r--r--gi/pygi-value.c720
1 files changed, 719 insertions, 1 deletions
diff --git a/gi/pygi-value.c b/gi/pygi-value.c
index 6ac12cf0..f2cc27b2 100644
--- a/gi/pygi-value.c
+++ b/gi/pygi-value.c
@@ -17,7 +17,10 @@
*/
#include "pygi-value.h"
-
+#include "pyglib-python-compat.h"
+#include "pygobject-private.h"
+#include "pygtype.h"
+#include "pygparamspec.h"
GIArgument
_pygi_argument_from_g_value(const GValue *value,
@@ -142,3 +145,718 @@ _pygi_argument_from_g_value(const GValue *value,
return arg;
}
+
+
+static int
+pyg_value_array_from_pyobject(GValue *value,
+ PyObject *obj,
+ const GParamSpecValueArray *pspec)
+{
+ int len;
+ GValueArray *value_array;
+ int i;
+
+ len = PySequence_Length(obj);
+ if (len == -1) {
+ PyErr_Clear();
+ return -1;
+ }
+
+ if (pspec && pspec->fixed_n_elements > 0 && len != pspec->fixed_n_elements)
+ return -1;
+
+ value_array = g_value_array_new(len);
+
+ for (i = 0; i < len; ++i) {
+ PyObject *item = PySequence_GetItem(obj, i);
+ GType type;
+ GValue item_value = { 0, };
+ int status;
+
+ if (! item) {
+ PyErr_Clear();
+ g_value_array_free(value_array);
+ return -1;
+ }
+
+ if (pspec && pspec->element_spec)
+ type = G_PARAM_SPEC_VALUE_TYPE(pspec->element_spec);
+ else if (item == Py_None)
+ type = G_TYPE_POINTER; /* store None as NULL */
+ else {
+ type = pyg_type_from_object((PyObject*)Py_TYPE(item));
+ if (! type) {
+ PyErr_Clear();
+ g_value_array_free(value_array);
+ Py_DECREF(item);
+ return -1;
+ }
+ }
+
+ g_value_init(&item_value, type);
+ status = (pspec && pspec->element_spec)
+ ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
+ : pyg_value_from_pyobject(&item_value, item);
+ Py_DECREF(item);
+
+ if (status == -1) {
+ g_value_array_free(value_array);
+ g_value_unset(&item_value);
+ return -1;
+ }
+
+ g_value_array_append(value_array, &item_value);
+ g_value_unset(&item_value);
+ }
+
+ g_value_take_boxed(value, value_array);
+ return 0;
+}
+
+static int
+pyg_array_from_pyobject(GValue *value,
+ PyObject *obj)
+{
+ int len;
+ GArray *array;
+ int i;
+
+ len = PySequence_Length(obj);
+ if (len == -1) {
+ PyErr_Clear();
+ return -1;
+ }
+
+ array = g_array_new(FALSE, TRUE, sizeof(GValue));
+
+ for (i = 0; i < len; ++i) {
+ PyObject *item = PySequence_GetItem(obj, i);
+ GType type;
+ GValue item_value = { 0, };
+ int status;
+
+ if (! item) {
+ PyErr_Clear();
+ g_array_free(array, FALSE);
+ return -1;
+ }
+
+ if (item == Py_None)
+ type = G_TYPE_POINTER; /* store None as NULL */
+ else {
+ type = pyg_type_from_object((PyObject*)Py_TYPE(item));
+ if (! type) {
+ PyErr_Clear();
+ g_array_free(array, FALSE);
+ Py_DECREF(item);
+ return -1;
+ }
+ }
+
+ g_value_init(&item_value, type);
+ status = pyg_value_from_pyobject(&item_value, item);
+ Py_DECREF(item);
+
+ if (status == -1) {
+ g_array_free(array, FALSE);
+ g_value_unset(&item_value);
+ return -1;
+ }
+
+ g_array_append_val(array, item_value);
+ }
+
+ g_value_take_boxed(value, array);
+ return 0;
+}
+
+/**
+ * pyg_value_from_pyobject_with_error:
+ * @value: the GValue object to store the converted value in.
+ * @obj: the Python object to convert.
+ *
+ * This function converts a Python object and stores the result in a
+ * GValue. The GValue must be initialised in advance with
+ * g_value_init(). If the Python object can't be converted to the
+ * type of the GValue, then an error is returned.
+ *
+ * Returns: 0 on success, -1 on error.
+ */
+int
+pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
+{
+ PyObject *tmp;
+ GType value_type = G_VALUE_TYPE(value);
+
+ switch (G_TYPE_FUNDAMENTAL(value_type)) {
+ case G_TYPE_INTERFACE:
+ /* we only handle interface types that have a GObject prereq */
+ if (g_type_is_a(value_type, G_TYPE_OBJECT)) {
+ if (obj == Py_None)
+ g_value_set_object(value, NULL);
+ else {
+ if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
+ PyErr_SetString(PyExc_TypeError, "GObject is required");
+ return -1;
+ }
+ if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
+ value_type)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid GObject type for assignment");
+ return -1;
+ }
+ g_value_set_object(value, pygobject_get(obj));
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Unsupported conversion");
+ return -1;
+ }
+ break;
+ case G_TYPE_CHAR:
+ if (PYGLIB_PyLong_Check(obj)) {
+ glong val;
+ val = PYGLIB_PyLong_AsLong(obj);
+ if (val >= -128 && val <= 127)
+ g_value_set_schar(value, (gchar) val);
+ else
+ return -1;
+ }
+#if PY_VERSION_HEX < 0x03000000
+ else if (PyString_Check(obj)) {
+ g_value_set_schar(value, PyString_AsString(obj)[0]);
+ }
+#endif
+ else if (PyUnicode_Check(obj)) {
+ tmp = PyUnicode_AsUTF8String(obj);
+ g_value_set_schar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
+ Py_DECREF(tmp);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Cannot convert to TYPE_CHAR");
+ return -1;
+ }
+
+ break;
+ case G_TYPE_UCHAR:
+ if (PYGLIB_PyLong_Check(obj)) {
+ glong val;
+ val = PYGLIB_PyLong_AsLong(obj);
+ if (val >= 0 && val <= 255)
+ g_value_set_uchar(value, (guchar) val);
+ else
+ return -1;
+#if PY_VERSION_HEX < 0x03000000
+ } else if (PyString_Check(obj)) {
+ g_value_set_uchar(value, PyString_AsString(obj)[0]);
+#endif
+ } else if (PyUnicode_Check(obj)) {
+ tmp = PyUnicode_AsUTF8String(obj);
+ g_value_set_uchar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
+ Py_DECREF(tmp);
+ } else {
+ PyErr_Clear();
+ return -1;
+ }
+ break;
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean(value, PyObject_IsTrue(obj));
+ break;
+ case G_TYPE_INT:
+ g_value_set_int(value, PYGLIB_PyLong_AsLong(obj));
+ break;
+ case G_TYPE_UINT:
+ {
+ if (PYGLIB_PyLong_Check(obj)) {
+ guint val;
+
+ /* check that number is not negative */
+ if (PyLong_AsLongLong(obj) < 0)
+ return -1;
+
+ val = PyLong_AsUnsignedLong(obj);
+ if (val <= G_MAXUINT)
+ g_value_set_uint(value, val);
+ else
+ return -1;
+ } else {
+ g_value_set_uint(value, PyLong_AsUnsignedLong(obj));
+ }
+ }
+ break;
+ case G_TYPE_LONG:
+ g_value_set_long(value, PYGLIB_PyLong_AsLong(obj));
+ break;
+ case G_TYPE_ULONG:
+#if PY_VERSION_HEX < 0x03000000
+ if (PyInt_Check(obj)) {
+ long val;
+
+ val = PYGLIB_PyLong_AsLong(obj);
+ if (val < 0) {
+ PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
+ return -1;
+ }
+ g_value_set_ulong(value, (gulong)val);
+ } else
+#endif
+ if (PyLong_Check(obj))
+ g_value_set_ulong(value, PyLong_AsUnsignedLong(obj));
+ else
+ return -1;
+ break;
+ case G_TYPE_INT64:
+ g_value_set_int64(value, PyLong_AsLongLong(obj));
+ break;
+ case G_TYPE_UINT64:
+#if PY_VERSION_HEX < 0x03000000
+ if (PyInt_Check(obj)) {
+ long v = PyInt_AsLong(obj);
+ if (v < 0) {
+ PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
+ return -1;
+ }
+ g_value_set_uint64(value, v);
+ } else
+#endif
+ if (PyLong_Check(obj))
+ g_value_set_uint64(value, PyLong_AsUnsignedLongLong(obj));
+ else
+ return -1;
+ break;
+ case G_TYPE_ENUM:
+ {
+ gint val = 0;
+ if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
+ return -1;
+ }
+ g_value_set_enum(value, val);
+ }
+ break;
+ case G_TYPE_FLAGS:
+ {
+ guint val = 0;
+ if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
+ return -1;
+ }
+ g_value_set_flags(value, val);
+ }
+ break;
+ case G_TYPE_FLOAT:
+ g_value_set_float(value, PyFloat_AsDouble(obj));
+ break;
+ case G_TYPE_DOUBLE:
+ g_value_set_double(value, PyFloat_AsDouble(obj));
+ break;
+ case G_TYPE_STRING:
+ if (obj == Py_None) {
+ g_value_set_string(value, NULL);
+ } else {
+ PyObject* tmp_str = PyObject_Str(obj);
+ if (tmp_str == NULL) {
+ PyErr_Clear();
+ if (PyUnicode_Check(obj)) {
+ tmp = PyUnicode_AsUTF8String(obj);
+ g_value_set_string(value, PYGLIB_PyBytes_AsString(tmp));
+ Py_DECREF(tmp);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Expected string");
+ return -1;
+ }
+ } else {
+#if PY_VERSION_HEX < 0x03000000
+ g_value_set_string(value, PyString_AsString(tmp_str));
+#else
+ tmp = PyUnicode_AsUTF8String(tmp_str);
+ g_value_set_string(value, PyBytes_AsString(tmp));
+ Py_DECREF(tmp);
+#endif
+ }
+ Py_XDECREF(tmp_str);
+ }
+ break;
+ case G_TYPE_POINTER:
+ if (obj == Py_None)
+ g_value_set_pointer(value, NULL);
+ else if (PyObject_TypeCheck(obj, &PyGPointer_Type) &&
+ G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype))
+ g_value_set_pointer(value, pyg_pointer_get(obj, gpointer));
+ else if (PYGLIB_CPointer_Check(obj))
+ g_value_set_pointer(value, PYGLIB_CPointer_GetPointer(obj, NULL));
+ else if (G_VALUE_HOLDS_GTYPE (value))
+ g_value_set_gtype (value, pyg_type_from_object (obj));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected pointer");
+ return -1;
+ }
+ break;
+ case G_TYPE_BOXED: {
+ PyGTypeMarshal *bm;
+
+ if (obj == Py_None)
+ g_value_set_boxed(value, NULL);
+ else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
+ g_value_set_boxed(value, obj);
+ else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) &&
+ G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype))
+ g_value_set_boxed(value, pyg_boxed_get(obj, gpointer));
+ else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
+ GType type;
+ GValue *n_value;
+
+ type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
+ if (G_UNLIKELY (! type)) {
+ return -1;
+ }
+ n_value = g_new0 (GValue, 1);
+ g_value_init (n_value, type);
+ g_value_take_boxed (value, n_value);
+ return pyg_value_from_pyobject_with_error (n_value, obj);
+ }
+ else if (PySequence_Check(obj) &&
+ G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY))
+ return pyg_value_array_from_pyobject(value, obj, NULL);
+ else if (PySequence_Check(obj) &&
+ G_VALUE_HOLDS(value, G_TYPE_ARRAY))
+ return pyg_array_from_pyobject(value, obj);
+ else if (PYGLIB_PyUnicode_Check(obj) &&
+ G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
+ GString *string;
+ char *buffer;
+ Py_ssize_t len;
+ if (PYGLIB_PyUnicode_AsStringAndSize(obj, &buffer, &len))
+ return -1;
+ string = g_string_new_len(buffer, len);
+ g_value_set_boxed(value, string);
+ g_string_free (string, TRUE);
+ break;
+ }
+ else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
+ return bm->tovalue(value, obj);
+ else if (PYGLIB_CPointer_Check(obj))
+ g_value_set_boxed(value, PYGLIB_CPointer_GetPointer(obj, NULL));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected Boxed");
+ return -1;
+ }
+ break;
+ }
+ case G_TYPE_PARAM:
+ /* we need to support both the wrapped _gobject.GParamSpec and the GI
+ * GObject.ParamSpec */
+ if (G_IS_PARAM_SPEC (pygobject_get (obj)))
+ g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
+ else if (PyGParamSpec_Check(obj))
+ g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected ParamSpec");
+ return -1;
+ }
+ break;
+ case G_TYPE_OBJECT:
+ if (obj == Py_None) {
+ g_value_set_object(value, NULL);
+ } else if (PyObject_TypeCheck(obj, &PyGObject_Type) &&
+ G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
+ G_VALUE_TYPE(value))) {
+ g_value_set_object(value, pygobject_get(obj));
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Expected GObject");
+ return -1;
+ }
+ break;
+ case G_TYPE_VARIANT:
+ {
+ if (obj == Py_None)
+ g_value_set_variant(value, NULL);
+ else if (pyg_type_from_object_strict(obj, FALSE) == G_TYPE_VARIANT)
+ g_value_set_variant(value, pyg_boxed_get(obj, GVariant));
+ else {
+ PyErr_SetString(PyExc_TypeError, "Expected Variant");
+ return -1;
+ }
+ break;
+ }
+ default:
+ {
+ PyGTypeMarshal *bm;
+ if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) {
+ return bm->tovalue(value, obj);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Unknown value type");
+ return -1;
+ }
+ break;
+ }
+ }
+
+ /* If an error occurred, unset the GValue but don't clear the Python error. */
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * pyg_value_from_pyobject:
+ * @value: the GValue object to store the converted value in.
+ * @obj: the Python object to convert.
+ *
+ * Same basic function as pyg_value_from_pyobject_with_error but clears
+ * any Python errors before returning.
+ *
+ * Returns: 0 on success, -1 on error.
+ */
+int
+pyg_value_from_pyobject(GValue *value, PyObject *obj)
+{
+ int res = pyg_value_from_pyobject_with_error (value, obj);
+
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ return -1;
+ }
+ return res;
+}
+
+/**
+ * pyg_value_as_pyobject:
+ * @value: the GValue object.
+ * @copy_boxed: true if boxed values should be copied.
+ *
+ * This function creates/returns a Python wrapper object that
+ * represents the GValue passed as an argument.
+ *
+ * Returns: a PyObject representing the value.
+ */
+PyObject *
+pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed)
+{
+ gchar buf[128];
+
+ switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) {
+ case G_TYPE_INTERFACE:
+ if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT))
+ return pygobject_new(g_value_get_object(value));
+ else
+ break;
+ case G_TYPE_CHAR: {
+ gint8 val = g_value_get_schar(value);
+ return PYGLIB_PyUnicode_FromStringAndSize((char *)&val, 1);
+ }
+ case G_TYPE_UCHAR: {
+ guint8 val = g_value_get_uchar(value);
+ return PYGLIB_PyBytes_FromStringAndSize((char *)&val, 1);
+ }
+ case G_TYPE_BOOLEAN: {
+ return PyBool_FromLong(g_value_get_boolean(value));
+ }
+ case G_TYPE_INT:
+ return PYGLIB_PyLong_FromLong(g_value_get_int(value));
+ case G_TYPE_UINT:
+ {
+ /* in Python, the Int object is backed by a long. If a
+ long can hold the whole value of an unsigned int, use
+ an Int. Otherwise, use a Long object to avoid overflow.
+ This matches the ULongArg behavior in codegen/argtypes.h */
+#if (G_MAXUINT <= G_MAXLONG)
+ return PYGLIB_PyLong_FromLong((glong) g_value_get_uint(value));
+#else
+ return PyLong_FromUnsignedLong((gulong) g_value_get_uint(value));
+#endif
+ }
+ case G_TYPE_LONG:
+ return PYGLIB_PyLong_FromLong(g_value_get_long(value));
+ case G_TYPE_ULONG:
+ {
+ gulong val = g_value_get_ulong(value);
+
+ if (val <= G_MAXLONG)
+ return PYGLIB_PyLong_FromLong((glong) val);
+ else
+ return PyLong_FromUnsignedLong(val);
+ }
+ case G_TYPE_INT64:
+ {
+ gint64 val = g_value_get_int64(value);
+
+ if (G_MINLONG <= val && val <= G_MAXLONG)
+ return PYGLIB_PyLong_FromLong((glong) val);
+ else
+ return PyLong_FromLongLong(val);
+ }
+ case G_TYPE_UINT64:
+ {
+ guint64 val = g_value_get_uint64(value);
+
+ if (val <= G_MAXLONG)
+ return PYGLIB_PyLong_FromLong((glong) val);
+ else
+ return PyLong_FromUnsignedLongLong(val);
+ }
+ case G_TYPE_ENUM:
+ return pyg_enum_from_gtype(G_VALUE_TYPE(value), g_value_get_enum(value));
+ case G_TYPE_FLAGS:
+ return pyg_flags_from_gtype(G_VALUE_TYPE(value), g_value_get_flags(value));
+ case G_TYPE_FLOAT:
+ return PyFloat_FromDouble(g_value_get_float(value));
+ case G_TYPE_DOUBLE:
+ return PyFloat_FromDouble(g_value_get_double(value));
+ case G_TYPE_STRING:
+ {
+ const gchar *str = g_value_get_string(value);
+
+ if (str)
+ return PYGLIB_PyUnicode_FromString(str);
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ case G_TYPE_POINTER:
+ if (G_VALUE_HOLDS_GTYPE (value))
+ return pyg_type_wrapper_new (g_value_get_gtype (value));
+ else
+ return pyg_pointer_new(G_VALUE_TYPE(value),
+ g_value_get_pointer(value));
+ case G_TYPE_BOXED: {
+ PyGTypeMarshal *bm;
+
+ if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) {
+ PyObject *ret = (PyObject *)g_value_dup_boxed(value);
+ if (ret == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return ret;
+ } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
+ GValue *n_value = g_value_get_boxed (value);
+ return pyg_value_as_pyobject(n_value, copy_boxed);
+ } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY)) {
+ GValueArray *array = (GValueArray *) g_value_get_boxed(value);
+ PyObject *ret = PyList_New(array->n_values);
+ int i;
+ for (i = 0; i < array->n_values; ++i)
+ PyList_SET_ITEM(ret, i, pyg_value_as_pyobject
+ (array->values + i, copy_boxed));
+ return ret;
+ } else if (G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
+ GString *string = (GString *) g_value_get_boxed(value);
+ PyObject *ret = PYGLIB_PyUnicode_FromStringAndSize(string->str, string->len);
+ return ret;
+ }
+ bm = pyg_type_lookup(G_VALUE_TYPE(value));
+ if (bm) {
+ return bm->fromvalue(value);
+ } else {
+ if (copy_boxed)
+ return pyg_boxed_new(G_VALUE_TYPE(value),
+ g_value_get_boxed(value), TRUE, TRUE);
+ else
+ return pyg_boxed_new(G_VALUE_TYPE(value),
+ g_value_get_boxed(value),FALSE,FALSE);
+ }
+ }
+ case G_TYPE_PARAM:
+ return pyg_param_spec_new(g_value_get_param(value));
+ case G_TYPE_OBJECT:
+ return pygobject_new(g_value_get_object(value));
+ case G_TYPE_VARIANT:
+ {
+ GVariant *v = g_value_get_variant(value);
+ if (v == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return pyg_boxed_new(G_TYPE_VARIANT, g_variant_ref(v), FALSE, FALSE);
+ }
+ default:
+ {
+ PyGTypeMarshal *bm;
+ if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))))
+ return bm->fromvalue(value);
+ break;
+ }
+ }
+ g_snprintf(buf, sizeof(buf), "unknown type %s",
+ g_type_name(G_VALUE_TYPE(value)));
+ PyErr_SetString(PyExc_TypeError, buf);
+ return NULL;
+}
+
+
+int
+pyg_param_gvalue_from_pyobject(GValue* value,
+ PyObject* py_obj,
+ const GParamSpec* pspec)
+{
+ if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
+ gunichar u;
+
+ if (!pyg_pyobj_to_unichar_conv(py_obj, &u)) {
+ PyErr_Clear();
+ return -1;
+ }
+ g_value_set_uint(value, u);
+ return 0;
+ }
+ else if (G_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
+ return pyg_value_array_from_pyobject(value, py_obj,
+ G_PARAM_SPEC_VALUE_ARRAY(pspec));
+ else {
+ return pyg_value_from_pyobject(value, py_obj);
+ }
+}
+
+PyObject*
+pyg_param_gvalue_as_pyobject(const GValue* gvalue,
+ gboolean copy_boxed,
+ const GParamSpec* pspec)
+{
+ if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
+ gunichar u;
+ Py_UNICODE uni_buffer[2] = { 0, 0 };
+
+ u = g_value_get_uint(gvalue);
+ uni_buffer[0] = u;
+ return PyUnicode_FromUnicode(uni_buffer, 1);
+ }
+ else {
+ return pyg_value_as_pyobject(gvalue, copy_boxed);
+ }
+}
+
+PyObject *
+pyg_strv_from_gvalue(const GValue *value)
+{
+ gchar **argv = (gchar **) g_value_get_boxed(value);
+ int argc = 0, i;
+ PyObject *py_argv;
+
+ if (argv) {
+ while (argv[argc])
+ argc++;
+ }
+ py_argv = PyList_New(argc);
+ for (i = 0; i < argc; ++i)
+ PyList_SET_ITEM(py_argv, i, PYGLIB_PyUnicode_FromString(argv[i]));
+ return py_argv;
+}
+
+int
+pyg_strv_to_gvalue(GValue *value, PyObject *obj)
+{
+ Py_ssize_t argc, i;
+ gchar **argv;
+
+ if (!(PyTuple_Check(obj) || PyList_Check(obj)))
+ return -1;
+
+ argc = PySequence_Length(obj);
+ for (i = 0; i < argc; ++i)
+ if (!PYGLIB_PyUnicode_Check(PySequence_Fast_GET_ITEM(obj, i)))
+ return -1;
+ argv = g_new(gchar *, argc + 1);
+ for (i = 0; i < argc; ++i)
+ argv[i] = g_strdup(PYGLIB_PyUnicode_AsString(PySequence_Fast_GET_ITEM(obj, i)));
+ argv[i] = NULL;
+ g_value_take_boxed(value, argv);
+ return 0;
+}