diff options
Diffstat (limited to 'gobject/pygboxed.c')
| -rw-r--r-- | gobject/pygboxed.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/gobject/pygboxed.c b/gobject/pygboxed.c new file mode 100644 index 0000000..378c9a0 --- /dev/null +++ b/gobject/pygboxed.c @@ -0,0 +1,174 @@ +/* -*- mode: C; c-basic-indent: 4 -*- */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pygobject-private.h" + +static void +pyg_boxed_dealloc(PyGBoxed *self) +{ + if (self->free_on_dealloc && self->boxed) + g_boxed_free(self->gtype, self->boxed); + + self->ob_type->tp_free((PyObject *)self); +} + +static int +pyg_boxed_compare(PyGBoxed *self, PyGBoxed *v) +{ + if (self->boxed == v->boxed) return 0; + if (self->boxed > v->boxed) return -1; + return 1; +} + +static long +pyg_boxed_hash(PyGBoxed *self) +{ + return (long)self->boxed; +} + +static PyObject * +pyg_boxed_repr(PyGBoxed *self) +{ + gchar buf[128]; + + g_snprintf(buf, sizeof(buf), "<%s at 0x%lx>", g_type_name(self->gtype), + (long)self->boxed); + return PyString_FromString(buf); +} + +static int +pyg_boxed_init(PyGBoxed *self, PyObject *args, PyObject *kwargs) +{ + gchar buf[512]; + + if (!PyArg_ParseTuple(args, ":GBoxed.__init__")) + return -1; + + self->boxed = NULL; + self->gtype = 0; + self->free_on_dealloc = FALSE; + + g_snprintf(buf, sizeof(buf), "%s can not be constructed", self->ob_type->tp_name); + PyErr_SetString(PyExc_NotImplementedError, buf); + return -1; +} + +static void +pyg_boxed_free(PyObject *op) +{ + PyObject_FREE(op); +} + +PyTypeObject PyGBoxed_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gobject.GBoxed", /* tp_name */ + sizeof(PyGBoxed), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyg_boxed_dealloc, /* tp_dealloc */ + (printfunc)0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + (cmpfunc)pyg_boxed_compare, /* tp_compare */ + (reprfunc)pyg_boxed_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)pyg_boxed_hash, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + (getattrofunc)0, /* tp_getattro */ + (setattrofunc)0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + NULL, /* Documentation string */ + (traverseproc)0, /* tp_traverse */ + (inquiry)0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)0, /* tp_iter */ + (iternextfunc)0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + (PyTypeObject *)0, /* tp_base */ + (PyObject *)0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pyg_boxed_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + pyg_boxed_free, /* tp_free */ + (inquiry)0, /* tp_is_gc */ + (PyObject *)0, /* tp_bases */ +}; + +static GHashTable *boxed_types = NULL; + +void +pyg_register_boxed(PyObject *dict, const gchar *class_name, + GType boxed_type, PyTypeObject *type) +{ + PyObject *o; + + g_return_if_fail(dict != NULL); + g_return_if_fail(class_name != NULL); + g_return_if_fail(boxed_type != 0); + + if (!boxed_types) + boxed_types = g_hash_table_new(g_direct_hash, g_direct_equal); + + if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_boxed_dealloc; + + type->ob_type = &PyType_Type; + type->tp_base = &PyGBoxed_Type; + + if (PyType_Ready(type) < 0) { + g_warning("could not get type `%s' ready", type->tp_name); + return; + } + + PyDict_SetItemString(type->tp_dict, "__gtype__", + o=pyg_type_wrapper_new(boxed_type)); + Py_DECREF(o); + + g_hash_table_insert(boxed_types, GUINT_TO_POINTER(boxed_type), type); + + PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type); +} + +PyObject * +pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed, + gboolean own_ref) +{ + PyGBoxed *self; + PyTypeObject *tp; + + g_return_val_if_fail(boxed_type != 0, NULL); + g_return_val_if_fail(!copy_boxed || (copy_boxed && own_ref), NULL); + + if (!boxed) { + Py_INCREF(Py_None); + return Py_None; + } + + tp = g_hash_table_lookup(boxed_types, GUINT_TO_POINTER(boxed_type)); + if (!tp) + tp = (PyTypeObject *)&PyGBoxed_Type; /* fallback */ + self = PyObject_NEW(PyGBoxed, tp); + + if (self == NULL) + return NULL; + + if (copy_boxed) + boxed = g_boxed_copy(boxed_type, boxed); + self->boxed = boxed; + self->gtype = boxed_type; + self->free_on_dealloc = own_ref; + + return (PyObject *)self; +} |
