summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Feltman <sfeltman@src.gnome.org>2014-01-12 12:26:30 -0800
committerSimon Feltman <sfeltman@src.gnome.org>2014-02-02 16:02:58 -0800
commit204f5a187782c5325ed6bed96c9a940f3aa67d04 (patch)
tree71a1cc171e3c279fefdcfa0880ae797d93486b46
parentb8120d848dc5d36832123b1a913015f6e1fd8cdc (diff)
downloadpygobject-204f5a187782c5325ed6bed96c9a940f3aa67d04.tar.gz
marshal refactoring: Move GValue marshaling from pytype into pygi-value
Move marshaling of GValues to and from PyObjects into pygi-value.c. Make PyGTypeMarshal struct and related functions accessible via pygtype.h. https://bugzilla.gnome.org/show_bug.cgi?id=709700
-rw-r--r--gi/gobjectmodule.c2
-rw-r--r--gi/pygi-struct-marshal.c1
-rw-r--r--gi/pygi-value.c720
-rw-r--r--gi/pygi-value.h12
-rw-r--r--gi/pygobject-private.h16
-rw-r--r--gi/pygobject.c2
-rw-r--r--gi/pygtype.c728
-rw-r--r--gi/pygtype.h17
8 files changed, 757 insertions, 741 deletions
diff --git a/gi/gobjectmodule.c b/gi/gobjectmodule.c
index 4c614f7b..82d52a13 100644
--- a/gi/gobjectmodule.c
+++ b/gi/gobjectmodule.c
@@ -38,6 +38,8 @@
#include "pygtype.h"
#include "pygoptiongroup.h"
+#include "pygi-value.h"
+
static GHashTable *log_handlers = NULL;
static gboolean log_handlers_disabled = FALSE;
diff --git a/gi/pygi-struct-marshal.c b/gi/pygi-struct-marshal.c
index a30f03e3..52573d65 100644
--- a/gi/pygi-struct-marshal.c
+++ b/gi/pygi-struct-marshal.c
@@ -24,6 +24,7 @@
#include "pygi-struct-marshal.h"
#include "pygi-private.h"
+#include "pygi-value.h"
/*
* _is_union_member - check to see if the py_arg is actually a member of the
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;
+}
diff --git a/gi/pygi-value.h b/gi/pygi-value.h
index 3e8d46a1..544da3c9 100644
--- a/gi/pygi-value.h
+++ b/gi/pygi-value.h
@@ -20,12 +20,24 @@
#include <glib-object.h>
#include <girepository.h>
+#include <Python.h>
G_BEGIN_DECLS
GIArgument _pygi_argument_from_g_value(const GValue *value,
GITypeInfo *type_info);
+int pyg_value_from_pyobject(GValue *value, PyObject *obj);
+int pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj);
+PyObject *pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed);
+int pyg_param_gvalue_from_pyobject(GValue* value,
+ PyObject* py_obj,
+ const GParamSpec* pspec);
+PyObject *pyg_param_gvalue_as_pyobject(const GValue* gvalue,
+ gboolean copy_boxed,
+ const GParamSpec* pspec);
+PyObject *pyg_strv_from_gvalue(const GValue *value);
+int pyg_strv_to_gvalue(GValue *value, PyObject *obj);
G_END_DECLS
diff --git a/gi/pygobject-private.h b/gi/pygobject-private.h
index f48d073b..be565d62 100644
--- a/gi/pygobject-private.h
+++ b/gi/pygobject-private.h
@@ -78,22 +78,6 @@ gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val);
gint pyg_flags_get_value (GType flag_type, PyObject *obj, guint *val);
int pyg_pyobj_to_unichar_conv (PyObject* py_obj, void* ptr);
-typedef PyObject *(* fromvaluefunc)(const GValue *value);
-typedef int (*tovaluefunc)(GValue *value, PyObject *obj);
-
-void pyg_register_gtype_custom(GType gtype,
- fromvaluefunc from_func,
- tovaluefunc to_func);
-int pyg_value_from_pyobject(GValue *value, PyObject *obj);
-int pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj);
-PyObject *pyg_value_as_pyobject(const GValue *value, gboolean copy_boxed);
-int pyg_param_gvalue_from_pyobject(GValue* value,
- PyObject* py_obj,
- const GParamSpec* pspec);
-PyObject *pyg_param_gvalue_as_pyobject(const GValue* gvalue,
- gboolean copy_boxed,
- const GParamSpec* pspec);
-
GClosure *pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data);
void pyg_closure_set_exception_handler(GClosure *closure,
PyClosureExceptionHandler handler);
diff --git a/gi/pygobject.c b/gi/pygobject.c
index 129f29ab..215376bf 100644
--- a/gi/pygobject.c
+++ b/gi/pygobject.c
@@ -30,7 +30,7 @@
#include "pygparamspec.h"
#include "pygi.h"
-
+#include "pygi-value.h"
static void pygobject_dealloc(PyGObject *self);
static int pygobject_traverse(PyGObject *self, visitproc visit, void *arg);
diff --git a/gi/pygtype.c b/gi/pygtype.c
index 9dc1153e..e1fb4e66 100644
--- a/gi/pygtype.c
+++ b/gi/pygtype.c
@@ -30,6 +30,8 @@
#include "pygparamspec.h"
#include "pygtype.h"
+#include "pygi-value.h"
+
/* -------------- __gtype__ objects ---------------------------- */
typedef struct {
@@ -449,8 +451,6 @@ pyg_type_from_object(PyObject *obj)
return pyg_type_from_object_strict(obj, TRUE);
}
-/* -------------- GValue marshalling ------------------ */
-
/**
* pyg_enum_get_value:
* @enum_type: the GType of the flag.
@@ -613,13 +613,9 @@ pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val)
return res;
}
-typedef struct {
- fromvaluefunc fromvalue;
- tovaluefunc tovalue;
-} PyGTypeMarshal;
static GQuark pyg_type_marshal_key = 0;
-static PyGTypeMarshal *
+PyGTypeMarshal *
pyg_type_lookup(GType type)
{
GType ptype = type;
@@ -661,640 +657,6 @@ pyg_register_gtype_custom(GType gtype,
g_type_set_qdata(gtype, pyg_type_marshal_key, tm);
}
-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;
-}
-
/* -------------- PyGClosure ----------------- */
static void
@@ -1817,92 +1179,12 @@ int pyg_pyobj_to_unichar_conv(PyObject* py_obj, void* ptr)
return 0;
}
-
-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);
- }
-}
-
gboolean
pyg_gtype_is_custom(GType gtype)
{
return g_type_get_qdata (gtype, pygobject_custom_key) != NULL;
}
-static 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;
-}
-
-static 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;
-}
-
void
pygobject_type_register_types(PyObject *d)
{
@@ -1922,6 +1204,6 @@ pygobject_type_register_types(PyObject *d)
PyGObjectDoc_Type.tp_descr_get = (descrgetfunc)object_doc_descr_get;
pyg_register_gtype_custom(G_TYPE_STRV,
- _pyg_strv_from_gvalue,
- _pyg_strv_to_gvalue);
+ pyg_strv_from_gvalue,
+ pyg_strv_to_gvalue);
}
diff --git a/gi/pygtype.h b/gi/pygtype.h
index 2f9e7add..204c1464 100644
--- a/gi/pygtype.h
+++ b/gi/pygtype.h
@@ -23,6 +23,23 @@
#ifndef __PYGOBJECT_TYPE_H__
#define __PYGOBJECT_TYPE_H__
+#include <glib-object.h>
+#include <Python.h>
+
+typedef PyObject *(* fromvaluefunc)(const GValue *value);
+typedef int (*tovaluefunc)(GValue *value, PyObject *obj);
+
+typedef struct {
+ fromvaluefunc fromvalue;
+ tovaluefunc tovalue;
+} PyGTypeMarshal;
+
+PyGTypeMarshal *pyg_type_lookup(GType type);
+
+void pyg_register_gtype_custom(GType gtype,
+ fromvaluefunc from_func,
+ tovaluefunc to_func);
+
void pygobject_type_register_types(PyObject *d);
#endif /* __PYGOBJECT_TYPE_H__ */