summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Henstridge <james@daa.com.au>2002-01-22 02:12:21 +0000
committerJames Henstridge <jamesh@src.gnome.org>2002-01-22 02:12:21 +0000
commit7278c4a1b42e81be6a0ce3836bb1b0f1c8ba9a64 (patch)
treeb8bdfc02ec76b6e395d338b46801408945fb9d1a
parente81043d549e259dec4909e02c091e207a98d2ca8 (diff)
downloadpygobject-7278c4a1b42e81be6a0ce3836bb1b0f1c8ba9a64.tar.gz
pygobject-7278c4a1b42e81be6a0ce3836bb1b0f1c8ba9a64.tar.xz
pygobject-7278c4a1b42e81be6a0ce3836bb1b0f1c8ba9a64.zip
don't create boxed_marshal hash table, and remove the type functions moved
2002-01-22 James Henstridge <james@daa.com.au> * gobjectmodule.c (initgobject): don't create boxed_marshal hash table, and remove the type functions moved to pygtype.c. * pygtype.c: move GType stuff here from gobjectmodule.c. (pyg_register_boxed_custom): store the custom boxed marshal functions as GType data, rather than in a separate hash table.
-rw-r--r--gobject/gobjectmodule.c560
-rw-r--r--gobject/pygobject-private.h20
-rw-r--r--gobject/pygtype.c558
3 files changed, 581 insertions, 557 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index c66cab3..78dfccd 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -55,80 +55,6 @@ object_gc_free(PyObject *op)
PyObject_GC_Del(op);
}
-/* -------------- __gtype__ objects ---------------------------- */
-
-typedef struct {
- PyObject_HEAD
- GType type;
-} PyGTypeWrapper;
-
-static int
-pyg_type_wrapper_compare(PyGTypeWrapper *self, PyGTypeWrapper *v)
-{
- if (self->type == v->type) return 0;
- if (self->type > v->type) return -1;
- return 1;
-}
-
-static long
-pyg_type_wrapper_hash(PyGTypeWrapper *self)
-{
- return (long)self->type;
-}
-
-static PyObject *
-pyg_type_wrapper_repr(PyGTypeWrapper *self)
-{
- char buf[80];
- const gchar *name = g_type_name(self->type);
-
- g_snprintf(buf, sizeof(buf), "<GType %s (%p)>",
- name?name:"invalid", self->type);
- return PyString_FromString(buf);
-}
-
-static void
-pyg_type_wrapper_dealloc(PyGTypeWrapper *self)
-{
- PyObject_DEL(self);
-}
-
-PyTypeObject PyGTypeWrapper_Type = {
- PyObject_HEAD_INIT(NULL)
- 0,
- "gobject.GType",
- sizeof(PyGTypeWrapper),
- 0,
- (destructor)pyg_type_wrapper_dealloc,
- (printfunc)0,
- (getattrfunc)0,
- (setattrfunc)0,
- (cmpfunc)pyg_type_wrapper_compare,
- (reprfunc)pyg_type_wrapper_repr,
- 0,
- 0,
- 0,
- (hashfunc)pyg_type_wrapper_hash,
- (ternaryfunc)0,
- (reprfunc)0,
- 0L,0L,0L,0L,
- NULL
-};
-
-PyObject *
-pyg_type_wrapper_new(GType type)
-{
- PyGTypeWrapper *self;
-
- self = (PyGTypeWrapper *)PyObject_NEW(PyGTypeWrapper,
- &PyGTypeWrapper_Type);
- if (self == NULL)
- return NULL;
-
- self->type = type;
- return (PyObject *)self;
-}
-
/* -------------- GParamSpec objects ---------------------------- */
typedef struct {
@@ -310,7 +236,7 @@ pygobject_register_wrapper(PyObject *self)
g_object_set_qdata(obj, pygobject_wrapper_key, self);
}
-static PyTypeObject *
+PyTypeObject *
pygobject_lookup_class(GType gtype)
{
PyTypeObject *type;
@@ -323,7 +249,7 @@ pygobject_lookup_class(GType gtype)
return type;
}
-static PyObject *
+PyObject *
pygobject_new(GObject *obj)
{
PyGObject *self;
@@ -365,7 +291,7 @@ pygobject_new(GObject *obj)
/* ---------------- GBoxed functions -------------------- */
-static GType PY_TYPE_OBJECT = 0;
+GType PY_TYPE_OBJECT = 0;
static gpointer
pyobject_copy(gpointer boxed)
@@ -385,484 +311,6 @@ pyobject_free(gpointer boxed)
}
-/* -------------- GValue marshalling ------------------ */
-
-static gint
-pyg_enum_get_value(GType enum_type, PyObject *obj, gint *val)
-{
- GEnumClass *eclass = NULL;
- gint res = -1;
-
- g_return_val_if_fail(val != NULL, -1);
- if (!obj) {
- *val = 0;
- res = 0;
- } else if (PyInt_Check(obj)) {
- *val = PyInt_AsLong(obj);
- res = 0;
- } else if (PyString_Check(obj)) {
- GEnumValue *info;
- char *str = PyString_AsString(obj);
-
- if (enum_type != G_TYPE_NONE)
- eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
- else {
- PyErr_SetString(PyExc_TypeError, "could not convert string to enum because there is no GType associated to look up the value");
- res = -1;
- }
- info = g_enum_get_value_by_name(eclass, str);
- g_type_class_unref(eclass);
-
- if (!info)
- info = g_enum_get_value_by_nick(eclass, str);
- if (info) {
- *val = info->value;
- res = 0;
- } else {
- PyErr_SetString(PyExc_TypeError, "could not convert string");
- res = -1;
- }
- } else {
- PyErr_SetString(PyExc_TypeError,"enum values must be strings or ints");
- res = -1;
- }
- return res;
-}
-
-static gint
-pyg_flags_get_value(GType flag_type, PyObject *obj, gint *val)
-{
- GFlagsClass *fclass = NULL;
- gint res = -1;
-
- g_return_val_if_fail(val != NULL, -1);
- if (!obj) {
- *val = 0;
- res = 0;
- } else if (PyInt_Check(obj)) {
- *val = PyInt_AsLong(obj);
- res = 0;
- } else if (PyString_Check(obj)) {
- GFlagsValue *info;
- char *str = PyString_AsString(obj);
-
- if (flag_type != G_TYPE_NONE)
- fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
- else {
- PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
- res = -1;
- }
- info = g_flags_get_value_by_name(fclass, str);
- g_type_class_unref(fclass);
-
- if (!info)
- info = g_flags_get_value_by_nick(fclass, str);
- if (info) {
- *val = info->value;
- res = 0;
- } else {
- PyErr_SetString(PyExc_TypeError, "could not convert string");
- res = -1;
- }
- } else if (PyTuple_Check(obj)) {
- int i, len;
-
- len = PyTuple_Size(obj);
- *val = 0;
- res = 0;
-
- if (flag_type != G_TYPE_NONE)
- fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
- else {
- PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
- res = -1;
- }
-
- for (i = 0; i < len; i++) {
- PyObject *item = PyTuple_GetItem(obj, i);
- char *str = PyString_AsString(item);
- GFlagsValue *info = g_flags_get_value_by_name(fclass, str);
-
- if (!info)
- info = g_flags_get_value_by_nick(fclass, str);
- if (info) {
- *val |= info->value;
- } else {
- PyErr_SetString(PyExc_TypeError, "could not convert string");
- res = -1;
- break;
- }
- }
- g_type_class_unref(fclass);
- } else {
- PyErr_SetString(PyExc_TypeError,
- "flag values must be strings, ints or tuples");
- res = -1;
- }
- return res;
-}
-
-GType
-pyg_type_from_object(PyObject *obj)
-{
- PyObject *gtype;
- GType type;
-
- /* NULL check */
- if (!obj) {
- PyErr_SetString(PyExc_TypeError, "can't get type from NULL object");
- return 0;
- }
-
- /* map some standard types to primitive GTypes ... */
- if (obj == Py_None)
- return G_TYPE_NONE;
- if (PyType_Check(obj)) {
- PyTypeObject *tp = (PyTypeObject *)obj;
-
- if (tp == &PyInt_Type)
- return G_TYPE_INT;
- else if (tp == &PyLong_Type)
- return G_TYPE_LONG;
- else if (tp == &PyFloat_Type)
- return G_TYPE_DOUBLE;
- else if (tp == &PyString_Type)
- return G_TYPE_STRING;
- else if (tp == &PyBaseObject_Type)
- return PY_TYPE_OBJECT;
- }
-
- if (obj->ob_type == &PyGTypeWrapper_Type) {
- return ((PyGTypeWrapper *)obj)->type;
- }
-
- /* handle strings */
- if (PyString_Check(obj)) {
- type = g_type_from_name(PyString_AsString(obj));
- if (type == 0)
- PyErr_SetString(PyExc_TypeError, "could not find named typecode");
- return type;
- }
-
- /* finally, look for a __gtype__ attribute on the object */
- gtype = PyObject_GetAttrString(obj, "__gtype__");
- if (gtype) {
- if (gtype->ob_type == &PyGTypeWrapper_Type) {
- type = ((PyGTypeWrapper *)gtype)->type;
- Py_DECREF(gtype);
- return type;
- }
- Py_DECREF(gtype);
- }
-
- PyErr_Clear();
- PyErr_SetString(PyExc_TypeError, "could not get typecode from object");
- return 0;
-}
-
-typedef PyObject *(* fromvaluefunc)(const GValue *value);
-typedef int (*tovaluefunc)(GValue *value, PyObject *obj);
-typedef struct {
- fromvaluefunc fromvalue;
- tovaluefunc tovalue;
-} PyGBoxedMarshal;
-static GHashTable *boxed_marshalers;
-#define pyg_boxed_lookup(boxed_type) \
- ((PyGBoxedMarshal *)g_hash_table_lookup(boxed_marshalers, \
- GUINT_TO_POINTER(boxed_type)))
-
-static void
-pyg_register_boxed_custom(GType boxed_type,
- PyObject *(* from_func)(const GValue *value),
- int (* to_func)(GValue *value, PyObject *obj))
-{
- PyGBoxedMarshal *bm = g_new(PyGBoxedMarshal, 1);
-
- bm->fromvalue = from_func;
- bm->tovalue = to_func;
- g_hash_table_insert(boxed_marshalers, GUINT_TO_POINTER(boxed_type), bm);
-}
-
-static int
-pyg_value_from_pyobject(GValue *value, PyObject *obj)
-{
- PyObject *tmp;
-
- switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) {
- case G_TYPE_CHAR:
- if ((tmp = PyObject_Str(obj)))
- g_value_set_char(value, PyString_AsString(tmp)[0]);
- else {
- PyErr_Clear();
- return -1;
- }
- Py_DECREF(tmp);
- break;
- case G_TYPE_UCHAR:
- if ((tmp = PyObject_Str(obj)))
- g_value_set_char(value, PyString_AsString(tmp)[0]);
- else {
- PyErr_Clear();
- return -1;
- }
- Py_DECREF(tmp);
- break;
- case G_TYPE_BOOLEAN:
- g_value_set_boolean(value, PyObject_IsTrue(obj));
- break;
- case G_TYPE_INT:
- g_value_set_int(value, PyInt_AsLong(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- break;
- case G_TYPE_UINT:
- {
- if (PyInt_Check(obj)) {
- glong val;
-
- val = PyInt_AsLong(obj);
- if (val >= 0 && val <= G_MAXUINT)
- g_value_set_uint(value, (guint)val);
- else
- return -1;
- } else {
- g_value_set_uint(value, PyLong_AsUnsignedLong(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- }
- }
- break;
- case G_TYPE_LONG:
- g_value_set_long(value, PyInt_AsLong(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- break;
- case G_TYPE_ULONG:
- {
- if (PyInt_Check(obj)) {
- glong val;
-
- val = PyInt_AsLong(obj);
- if (val >= 0)
- g_value_set_ulong(value, (gulong)val);
- else
- return -1;
- } else {
- g_value_set_ulong(value, PyLong_AsUnsignedLong(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- }
- }
- break;
- case G_TYPE_INT64:
- g_value_set_int64(value, PyLong_AsLongLong(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- break;
- case G_TYPE_UINT64:
- g_value_set_uint64(value, PyLong_AsUnsignedLongLong(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- break;
- case G_TYPE_FLOAT:
- g_value_set_float(value, PyFloat_AsDouble(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- break;
- case G_TYPE_DOUBLE:
- g_value_set_double(value, PyFloat_AsDouble(obj));
- if (PyErr_Occurred()) {
- g_value_unset(value);
- PyErr_Clear();
- return -1;
- }
- break;
- case G_TYPE_STRING:
- if ((tmp = PyObject_Str(obj)))
- g_value_set_string(value, PyString_AsString(tmp));
- else {
- PyErr_Clear();
- return -1;
- }
- Py_DECREF(tmp);
- break;
- case G_TYPE_OBJECT:
- {
- PyTypeObject *type =pygobject_lookup_class(G_VALUE_TYPE(value));
- if (!PyObject_TypeCheck(obj, type)) {
- return -1;
- }
- g_value_set_object(value, pygobject_get(obj));
- }
- 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_BOXED:
- {
- PyGBoxedMarshal *bm;
-
- 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 ((bm = pyg_boxed_lookup(G_VALUE_TYPE(value))) != NULL) {
- return bm->tovalue(value, obj);
- } else if (PyCObject_Check(obj)) {
- g_value_set_boxed(value, PyCObject_AsVoidPtr(obj));
- } else
- return -1;
- }
- break;
- case G_TYPE_POINTER:
- if (PyCObject_Check(obj))
- g_value_set_pointer(value, PyCObject_AsVoidPtr(obj));
- else
- return -1;
- break;
- default:
- break;
- }
- return 0;
-}
-
-static PyObject *
-pyg_value_as_pyobject(const GValue *value)
-{
- gchar buf[128];
-
- switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) {
- case G_TYPE_CHAR:
- {
- gint8 val = g_value_get_char(value);
- return PyString_FromStringAndSize((char *)&val, 1);
- }
- case G_TYPE_UCHAR:
- {
- guint8 val = g_value_get_uchar(value);
- return PyString_FromStringAndSize((char *)&val, 1);
- }
- case G_TYPE_BOOLEAN:
- return PyInt_FromLong(g_value_get_boolean(value));
- case G_TYPE_INT:
- return PyInt_FromLong(g_value_get_int(value));
- case G_TYPE_UINT:
- {
- gulong val = (gulong) g_value_get_uint(value);
-
- if (val <= G_MAXLONG)
- return PyInt_FromLong((glong) val);
- else
- return PyLong_FromUnsignedLong(val);
- }
- case G_TYPE_LONG:
- return PyInt_FromLong(g_value_get_long(value));
- case G_TYPE_ULONG:
- {
- gulong val = g_value_get_ulong(value);
-
- if (val <= G_MAXLONG)
- return PyInt_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 PyInt_FromLong((glong) val);
- else
- return PyLong_FromLongLong(val);
- }
- case G_TYPE_UINT64:
- {
- guint64 val = g_value_get_uint64(value);
-
- if (val <= G_MAXLONG)
- return PyInt_FromLong((glong) val);
- else
- return PyLong_FromUnsignedLongLong(val);
- }
- 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 PyString_FromString(str);
- Py_INCREF(Py_None);
- return Py_None;
- }
- case G_TYPE_OBJECT:
- return pygobject_new(g_value_get_object(value));
- case G_TYPE_ENUM:
- return PyInt_FromLong(g_value_get_enum(value));
- case G_TYPE_FLAGS:
- return PyInt_FromLong(g_value_get_flags(value));
- case G_TYPE_BOXED:
- {
- PyGBoxedMarshal *bm;
-
- if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
- return (PyObject *)g_value_dup_boxed(value);
-
- bm = pyg_boxed_lookup(G_VALUE_TYPE(value));
- if (bm)
- return bm->fromvalue(value);
- else
- return pyg_boxed_new(G_VALUE_TYPE(value),
- g_value_get_boxed(value), TRUE, TRUE);
- }
- case G_TYPE_POINTER:
- return PyCObject_FromVoidPtr(g_value_get_pointer(value), NULL);
- default:
- break;
- }
- g_snprintf(buf, sizeof(buf), "unknown type %s",
- g_type_name(G_VALUE_TYPE(value)));
- PyErr_SetString(PyExc_TypeError, buf);
- return NULL;
-}
-
/* -------------- PyGClosure ----------------- */
typedef struct _PyGClosure PyGClosure;
@@ -2935,8 +2383,6 @@ initgobject(void)
o=pyg_type_wrapper_new(G_TYPE_BOXED));
Py_DECREF(o);
- boxed_marshalers = g_hash_table_new(g_direct_hash, g_direct_equal);
-
tuple = Py_BuildValue ("(iii)", glib_major_version, glib_minor_version,
glib_micro_version);
PyDict_SetItemString(d, "glib_version", tuple);
diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h
index 819950d..8c1c637 100644
--- a/gobject/pygobject-private.h
+++ b/gobject/pygobject-private.h
@@ -10,9 +10,29 @@
/* from gobjectmodule.c */
+GType PY_TYPE_OBJECT;
+
+PyObject * pygobject_new (GObject *obj);
+PyTypeObject *pygobject_lookup_class (GType gtype);
+
+
+/* from pygtype.h */
+extern PyTypeObject PyGTypeWrapper_Type;
+
PyObject *pyg_type_wrapper_new (GType type);
GType pyg_type_from_object (PyObject *obj);
+gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val);
+gint pyg_flags_get_value (GType flag_type, PyObject *obj, gint *val);
+
+typedef PyObject *(* fromvaluefunc)(const GValue *value);
+typedef int (*tovaluefunc)(GValue *value, PyObject *obj);
+
+void pyg_register_boxed_custom(GType boxed_type,
+ fromvaluefunc from_func,
+ tovaluefunc to_func);
+int pyg_value_from_pyobject(GValue *value, PyObject *obj);
+PyObject *pyg_value_as_pyobject(const GValue *value);
/* from pygboxed.c */
extern PyTypeObject PyGBoxed_Type;
diff --git a/gobject/pygtype.c b/gobject/pygtype.c
new file mode 100644
index 0000000..fdda265
--- /dev/null
+++ b/gobject/pygtype.c
@@ -0,0 +1,558 @@
+/* -*- mode: C; c-basic-offset: 4 -*- */
+
+#include "pygobject-private.h"
+
+/* -------------- __gtype__ objects ---------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ GType type;
+} PyGTypeWrapper;
+
+static int
+pyg_type_wrapper_compare(PyGTypeWrapper *self, PyGTypeWrapper *v)
+{
+ if (self->type == v->type) return 0;
+ if (self->type > v->type) return -1;
+ return 1;
+}
+
+static long
+pyg_type_wrapper_hash(PyGTypeWrapper *self)
+{
+ return (long)self->type;
+}
+
+static PyObject *
+pyg_type_wrapper_repr(PyGTypeWrapper *self)
+{
+ char buf[80];
+ const gchar *name = g_type_name(self->type);
+
+ g_snprintf(buf, sizeof(buf), "<GType %s (%p)>",
+ name?name:"invalid", self->type);
+ return PyString_FromString(buf);
+}
+
+static void
+pyg_type_wrapper_dealloc(PyGTypeWrapper *self)
+{
+ PyObject_DEL(self);
+}
+
+PyTypeObject PyGTypeWrapper_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gobject.GType",
+ sizeof(PyGTypeWrapper),
+ 0,
+ (destructor)pyg_type_wrapper_dealloc,
+ (printfunc)0,
+ (getattrfunc)0,
+ (setattrfunc)0,
+ (cmpfunc)pyg_type_wrapper_compare,
+ (reprfunc)pyg_type_wrapper_repr,
+ 0,
+ 0,
+ 0,
+ (hashfunc)pyg_type_wrapper_hash,
+ (ternaryfunc)0,
+ (reprfunc)0,
+ 0L,0L,0L,0L,
+ NULL
+};
+
+PyObject *
+pyg_type_wrapper_new(GType type)
+{
+ PyGTypeWrapper *self;
+
+ self = (PyGTypeWrapper *)PyObject_NEW(PyGTypeWrapper,
+ &PyGTypeWrapper_Type);
+ if (self == NULL)
+ return NULL;
+
+ self->type = type;
+ return (PyObject *)self;
+}
+
+GType
+pyg_type_from_object(PyObject *obj)
+{
+ PyObject *gtype;
+ GType type;
+
+ /* NULL check */
+ if (!obj) {
+ PyErr_SetString(PyExc_TypeError, "can't get type from NULL object");
+ return 0;
+ }
+
+ /* map some standard types to primitive GTypes ... */
+ if (obj == Py_None)
+ return G_TYPE_NONE;
+ if (PyType_Check(obj)) {
+ PyTypeObject *tp = (PyTypeObject *)obj;
+
+ if (tp == &PyInt_Type)
+ return G_TYPE_INT;
+ else if (tp == &PyLong_Type)
+ return G_TYPE_LONG;
+ else if (tp == &PyFloat_Type)
+ return G_TYPE_DOUBLE;
+ else if (tp == &PyString_Type)
+ return G_TYPE_STRING;
+ else if (tp == &PyBaseObject_Type)
+ return PY_TYPE_OBJECT;
+ }
+
+ if (obj->ob_type == &PyGTypeWrapper_Type) {
+ return ((PyGTypeWrapper *)obj)->type;
+ }
+
+ /* handle strings */
+ if (PyString_Check(obj)) {
+ type = g_type_from_name(PyString_AsString(obj));
+ if (type == 0)
+ PyErr_SetString(PyExc_TypeError, "could not find named typecode");
+ return type;
+ }
+
+ /* finally, look for a __gtype__ attribute on the object */
+ gtype = PyObject_GetAttrString(obj, "__gtype__");
+ if (gtype) {
+ if (gtype->ob_type == &PyGTypeWrapper_Type) {
+ type = ((PyGTypeWrapper *)gtype)->type;
+ Py_DECREF(gtype);
+ return type;
+ }
+ Py_DECREF(gtype);
+ }
+
+ PyErr_Clear();
+ PyErr_SetString(PyExc_TypeError, "could not get typecode from object");
+ return 0;
+}
+
+/* -------------- GValue marshalling ------------------ */
+
+gint
+pyg_enum_get_value(GType enum_type, PyObject *obj, gint *val)
+{
+ GEnumClass *eclass = NULL;
+ gint res = -1;
+
+ g_return_val_if_fail(val != NULL, -1);
+ if (!obj) {
+ *val = 0;
+ res = 0;
+ } else if (PyInt_Check(obj)) {
+ *val = PyInt_AsLong(obj);
+ res = 0;
+ } else if (PyString_Check(obj)) {
+ GEnumValue *info;
+ char *str = PyString_AsString(obj);
+
+ if (enum_type != G_TYPE_NONE)
+ eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
+ else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string to enum because there is no GType associated to look up the value");
+ res = -1;
+ }
+ info = g_enum_get_value_by_name(eclass, str);
+ g_type_class_unref(eclass);
+
+ if (!info)
+ info = g_enum_get_value_by_nick(eclass, str);
+ if (info) {
+ *val = info->value;
+ res = 0;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string");
+ res = -1;
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError,"enum values must be strings or ints");
+ res = -1;
+ }
+ return res;
+}
+
+gint
+pyg_flags_get_value(GType flag_type, PyObject *obj, gint *val)
+{
+ GFlagsClass *fclass = NULL;
+ gint res = -1;
+
+ g_return_val_if_fail(val != NULL, -1);
+ if (!obj) {
+ *val = 0;
+ res = 0;
+ } else if (PyInt_Check(obj)) {
+ *val = PyInt_AsLong(obj);
+ res = 0;
+ } else if (PyString_Check(obj)) {
+ GFlagsValue *info;
+ char *str = PyString_AsString(obj);
+
+ if (flag_type != G_TYPE_NONE)
+ fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
+ else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
+ res = -1;
+ }
+ info = g_flags_get_value_by_name(fclass, str);
+ g_type_class_unref(fclass);
+
+ if (!info)
+ info = g_flags_get_value_by_nick(fclass, str);
+ if (info) {
+ *val = info->value;
+ res = 0;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string");
+ res = -1;
+ }
+ } else if (PyTuple_Check(obj)) {
+ int i, len;
+
+ len = PyTuple_Size(obj);
+ *val = 0;
+ res = 0;
+
+ if (flag_type != G_TYPE_NONE)
+ fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
+ else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
+ res = -1;
+ }
+
+ for (i = 0; i < len; i++) {
+ PyObject *item = PyTuple_GetItem(obj, i);
+ char *str = PyString_AsString(item);
+ GFlagsValue *info = g_flags_get_value_by_name(fclass, str);
+
+ if (!info)
+ info = g_flags_get_value_by_nick(fclass, str);
+ if (info) {
+ *val |= info->value;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "could not convert string");
+ res = -1;
+ break;
+ }
+ }
+ g_type_class_unref(fclass);
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "flag values must be strings, ints or tuples");
+ res = -1;
+ }
+ return res;
+}
+
+typedef struct {
+ fromvaluefunc fromvalue;
+ tovaluefunc tovalue;
+} PyGBoxedMarshal;
+static GQuark pyg_boxed_marshal_key = 0;
+
+#define pyg_boxed_lookup(boxed_type) \
+ ((PyGBoxedMarshal *)g_type_get_qdata((boxed_type), pyg_boxed_marshal_key))
+
+void
+pyg_register_boxed_custom(GType boxed_type,
+ fromvaluefunc from_func,
+ tovaluefunc to_func)
+{
+ PyGBoxedMarshal *bm;
+
+ if (!pyg_boxed_marshal_key)
+ pyg_boxed_marshal_key = g_quark_from_static_string("PyGBoxed::marshal");
+
+ bm = g_new(PyGBoxedMarshal, 1);
+ bm->fromvalue = from_func;
+ bm->tovalue = to_func;
+ g_type_set_qdata(boxed_type, pyg_boxed_marshal_key, bm);
+}
+
+int
+pyg_value_from_pyobject(GValue *value, PyObject *obj)
+{
+ PyObject *tmp;
+
+ switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) {
+ case G_TYPE_CHAR:
+ if ((tmp = PyObject_Str(obj)))
+ g_value_set_char(value, PyString_AsString(tmp)[0]);
+ else {
+ PyErr_Clear();
+ return -1;
+ }
+ Py_DECREF(tmp);
+ break;
+ case G_TYPE_UCHAR:
+ if ((tmp = PyObject_Str(obj)))
+ g_value_set_char(value, PyString_AsString(tmp)[0]);
+ else {
+ PyErr_Clear();
+ return -1;
+ }
+ Py_DECREF(tmp);
+ break;
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean(value, PyObject_IsTrue(obj));
+ break;
+ case G_TYPE_INT:
+ g_value_set_int(value, PyInt_AsLong(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ break;
+ case G_TYPE_UINT:
+ {
+ if (PyInt_Check(obj)) {
+ glong val;
+
+ val = PyInt_AsLong(obj);
+ if (val >= 0 && val <= G_MAXUINT)
+ g_value_set_uint(value, (guint)val);
+ else
+ return -1;
+ } else {
+ g_value_set_uint(value, PyLong_AsUnsignedLong(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ }
+ }
+ break;
+ case G_TYPE_LONG:
+ g_value_set_long(value, PyInt_AsLong(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ break;
+ case G_TYPE_ULONG:
+ {
+ if (PyInt_Check(obj)) {
+ glong val;
+
+ val = PyInt_AsLong(obj);
+ if (val >= 0)
+ g_value_set_ulong(value, (gulong)val);
+ else
+ return -1;
+ } else {
+ g_value_set_ulong(value, PyLong_AsUnsignedLong(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ }
+ }
+ break;
+ case G_TYPE_INT64:
+ g_value_set_int64(value, PyLong_AsLongLong(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ break;
+ case G_TYPE_UINT64:
+ g_value_set_uint64(value, PyLong_AsUnsignedLongLong(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ break;
+ case G_TYPE_FLOAT:
+ g_value_set_float(value, PyFloat_AsDouble(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ break;
+ case G_TYPE_DOUBLE:
+ g_value_set_double(value, PyFloat_AsDouble(obj));
+ if (PyErr_Occurred()) {
+ g_value_unset(value);
+ PyErr_Clear();
+ return -1;
+ }
+ break;
+ case G_TYPE_STRING:
+ if ((tmp = PyObject_Str(obj)))
+ g_value_set_string(value, PyString_AsString(tmp));
+ else {
+ PyErr_Clear();
+ return -1;
+ }
+ Py_DECREF(tmp);
+ break;
+ case G_TYPE_OBJECT:
+ {
+ PyTypeObject *type = pygobject_lookup_class(G_VALUE_TYPE(value));
+ if (!PyObject_TypeCheck(obj, type)) {
+ return -1;
+ }
+ g_value_set_object(value, pygobject_get(obj));
+ }
+ 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_BOXED:
+ {
+ PyGBoxedMarshal *bm;
+
+ 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 ((bm = pyg_boxed_lookup(G_VALUE_TYPE(value))) != NULL) {
+ return bm->tovalue(value, obj);
+ } else if (PyCObject_Check(obj)) {
+ g_value_set_boxed(value, PyCObject_AsVoidPtr(obj));
+ } else
+ return -1;
+ }
+ break;
+ case G_TYPE_POINTER:
+ if (PyCObject_Check(obj))
+ g_value_set_pointer(value, PyCObject_AsVoidPtr(obj));
+ else
+ return -1;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+PyObject *
+pyg_value_as_pyobject(const GValue *value)
+{
+ gchar buf[128];
+
+ switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) {
+ case G_TYPE_CHAR:
+ {
+ gint8 val = g_value_get_char(value);
+ return PyString_FromStringAndSize((char *)&val, 1);
+ }
+ case G_TYPE_UCHAR:
+ {
+ guint8 val = g_value_get_uchar(value);
+ return PyString_FromStringAndSize((char *)&val, 1);
+ }
+ case G_TYPE_BOOLEAN:
+ return PyInt_FromLong(g_value_get_boolean(value));
+ case G_TYPE_INT:
+ return PyInt_FromLong(g_value_get_int(value));
+ case G_TYPE_UINT:
+ {
+ gulong val = (gulong) g_value_get_uint(value);
+
+ if (val <= G_MAXLONG)
+ return PyInt_FromLong((glong) val);
+ else
+ return PyLong_FromUnsignedLong(val);
+ }
+ case G_TYPE_LONG:
+ return PyInt_FromLong(g_value_get_long(value));
+ case G_TYPE_ULONG:
+ {
+ gulong val = g_value_get_ulong(value);
+
+ if (val <= G_MAXLONG)
+ return PyInt_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 PyInt_FromLong((glong) val);
+ else
+ return PyLong_FromLongLong(val);
+ }
+ case G_TYPE_UINT64:
+ {
+ guint64 val = g_value_get_uint64(value);
+
+ if (val <= G_MAXLONG)
+ return PyInt_FromLong((glong) val);
+ else
+ return PyLong_FromUnsignedLongLong(val);
+ }
+ 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 PyString_FromString(str);
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ case G_TYPE_OBJECT:
+ return pygobject_new(g_value_get_object(value));
+ case G_TYPE_ENUM:
+ return PyInt_FromLong(g_value_get_enum(value));
+ case G_TYPE_FLAGS:
+ return PyInt_FromLong(g_value_get_flags(value));
+ case G_TYPE_BOXED:
+ {
+ PyGBoxedMarshal *bm;
+
+ if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
+ return (PyObject *)g_value_dup_boxed(value);
+
+ bm = pyg_boxed_lookup(G_VALUE_TYPE(value));
+ if (bm)
+ return bm->fromvalue(value);
+ else
+ return pyg_boxed_new(G_VALUE_TYPE(value),
+ g_value_get_boxed(value), TRUE, TRUE);
+ }
+ case G_TYPE_POINTER:
+ return PyCObject_FromVoidPtr(g_value_get_pointer(value), NULL);
+ default:
+ break;
+ }
+ g_snprintf(buf, sizeof(buf), "unknown type %s",
+ g_type_name(G_VALUE_TYPE(value)));
+ PyErr_SetString(PyExc_TypeError, buf);
+ return NULL;
+}
+