summaryrefslogtreecommitdiffstats
path: root/gobject/pygboxed.c
diff options
context:
space:
mode:
Diffstat (limited to 'gobject/pygboxed.c')
-rw-r--r--gobject/pygboxed.c174
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;
+}