diff options
| author | James Henstridge <james@daa.com.au> | 2001-06-08 15:49:13 +0000 |
|---|---|---|
| committer | James Henstridge <jamesh@src.gnome.org> | 2001-06-08 15:49:13 +0000 |
| commit | e8150173e5f35daeda0e1983beaa29a8ec0dfebf (patch) | |
| tree | f32879c7db987d370f7e2d300f6698bd888baeed | |
| parent | 4a9a14997dc9d70e8e77a1c37ec3e06a109af300 (diff) | |
| download | pygobject-e8150173e5f35daeda0e1983beaa29a8ec0dfebf.tar.gz pygobject-e8150173e5f35daeda0e1983beaa29a8ec0dfebf.tar.xz pygobject-e8150173e5f35daeda0e1983beaa29a8ec0dfebf.zip | |
function to register a new boxed type ExtensionClass. (pyg_boxed_new): new
2001-06-08 James Henstridge <james@daa.com.au>
* gobjectmodule.c (pyg_register_boxed): function to register a new
boxed type ExtensionClass.
(pyg_boxed_new): new function to create wrapper instances for a
particular boxed type (given its typecode).
2001-06-07 James Henstridge <james@daa.com.au>
* pygobject.h (pyg_boxed_get): add prototypes for a PyGBoxed type
that will be used for all boxed types in pygtk (well, I can hope
:)
* gobjectmodule.c (pyg_register_interface): new function to
register interfaces with. Makes sure I don't accidentally give
the interface a parent class :). Also adds a __gtype__ class
attribute similar to GObject classes. May also make interfaces
subclasses of GInterface at some point.
| -rw-r--r-- | gobject/gobjectmodule.c | 187 | ||||
| -rw-r--r-- | gobject/pygobject.h | 21 |
2 files changed, 207 insertions, 1 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index daaab4b..3f38fa4 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -272,6 +272,165 @@ pygobject_new(GObject *obj) return (PyObject *)self; } +/* ---------------- GBoxed functions -------------------- */ + +static void +pyg_boxed_dealloc(PyGBoxed *self) +{ + if (self->free_on_dealloc && self->boxed) + g_boxed_free(self->gtype, self->boxed); + PyMem_DEL(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 PyObject * +pyg_boxed__class_init__(PyObject *self, PyObject *args) +{ + PyExtensionClass *subclass; + + if (!PyArg_ParseTuple(args, "O:GBoxed.__class_init__", &subclass)) + return NULL; + + g_message("subclassing GBoxed types is bad m'kay"); + PyErr_SetString(PyExc_TypeError, "attempt to subclass a boxed type"); + return NULL; +} + +static PyObject * +pyg_boxed_init(PyGBoxed *self, PyObject *args) +{ + gchar buf[512]; + + if (!PyArg_ParseTuple(args, ":GBoxed.__init__")) + return NULL; + + 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 NULL; +} + +static PyMethodDef pyg_boxed_methods[] = { + {"__class_init__",pyg_boxed__class_init__, METH_VARARGS|METH_CLASS_METHOD}, + {"__init__", (PyCFunction)pyg_boxed_init, METH_VARARGS}, + {NULL,NULL,0} +}; + +static PyExtensionClass PyGBoxed_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "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 */ + /* Space for future expansion */ + 0L, 0L, + NULL, /* Documentation string */ + METHOD_CHAIN(pyg_boxed_methods), + 0, +}; + +static GHashTable *boxed_types = NULL; + +static void +pyg_register_boxed(PyObject *dict, const gchar *class_name, + GType boxed_type, PyExtensionClass *ec) +{ + PyObject *o; + + g_return_if_fail(dict != NULL); + g_return_if_fail(class_name != NULL); + g_return_if_fail(boxed_type != 0); + g_return_if_fail(ec != NULL); + + if (!boxed_types) + boxed_types = g_hash_table_new(g_direct_hash, g_direct_equal); + + if (!ec->tp_dealloc) ec->tp_dealloc = (destructor)pyg_boxed_dealloc; + if (!ec->tp_compare) ec->tp_compare = (cmpfunc)pyg_boxed_compare; + if (!ec->tp_hash) ec->tp_hash = (hashfunc)pyg_boxed_hash; + if (!ec->tp_repr) ec->tp_repr = (reprfunc)pyg_boxed_repr; + + PyExtensionClass_ExportSubclassSingle(dict, (char *)class_name, *ec, + PyGBoxed_Type); + PyDict_SetItemString(ec->class_dictionary, "__gtype__", + o=PyInt_FromLong(boxed_type)); + Py_DECREF(o); + g_hash_table_insert(boxed_types, GUINT_TO_POINTER(boxed_type), ec); +} + +static PyObject * +pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed, + gboolean own_ref) +{ + PyGBoxed *self; + PyTypeObject *tp; + + g_return_if_fail(boxed_type != 0); + g_return_if_fail(!copy_boxed || (copy_boxed && own_ref)); + + 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; +} + /* -------------- GValue marshalling ------------------ */ static gint @@ -1406,6 +1565,24 @@ static PyExtensionClass PyGObject_Type = { EXTENSIONCLASS_INSTDICT_FLAG, }; +/* ---------------- GInterface functions -------------------- */ + +static void +pyg_register_interface(PyObject *dict, const gchar *class_name, + GType (* get_type)(void), PyExtensionClass *ec) +{ + PyObject *o; + + PyExtensionClass_Export(dict, (char *)class_name, *ec); + + if (get_type) { + o = pyg_type_thingee_new(get_type); + PyDict_SetItemString(ec->class_dictionary, "__gtype__", o); + Py_DECREF(o); + } +} + + /* ---------------- gobject module functions -------------------- */ static PyObject * @@ -1697,6 +1874,11 @@ static struct _PyGObject_Functions functions = { pyg_boxed_register, pyg_value_from_pyobject, pyg_value_as_pyobject, + + pyg_register_interface, + + pyg_register_boxed, + pyg_boxed_new, }; DL_EXPORT(void) @@ -1713,6 +1895,11 @@ initgobject(void) o=PyInt_FromLong(G_TYPE_OBJECT)); Py_DECREF(o); + PyExtensionClass_Export(d, "GBoxed", PyGBoxed_Type); + PyDict_SetItemString(PyGBoxed_Type.class_dictionary, "__gtype__", + o=PyInt_FromLong(G_TYPE_BOXED)); + Py_DECREF(o); + boxed_marshalers = g_hash_table_new(g_direct_hash, g_direct_equal); pygobject_wrapper_key = g_quark_from_static_string("py-gobject-wrapper"); diff --git a/gobject/pygobject.h b/gobject/pygobject.h index 71b3b33..f2d15fe 100644 --- a/gobject/pygobject.h +++ b/gobject/pygobject.h @@ -15,9 +15,19 @@ typedef struct { PyObject *inst_dict; /* the instance dictionary -- must be last */ } PyGObject; -#define pygobject_get(v) (((PyGObject *)v)->obj) +#define pygobject_get(v) (((PyGObject *)(v))->obj) #define pygobject_check(v,base) (ExtensionClassSubclassInstance_Check(v,base)) +typedef struct { + PyObject_HEAD + gpointer boxed; + GType gtype; + gboolean free_on_dealloc; +} PyGBoxed; + +#define pyg_boxed_get(v,t) ((t *)((PyGBoxed *)(v))->boxed) +#define pyg_boxed_check(v,base) (ExtensionClassSubclassInstance_Check(v,base)) + struct _PyGObject_Functions { void (* register_class)(PyObject *dict, const gchar *class_name, GType (* get_type)(void), @@ -32,6 +42,14 @@ struct _PyGObject_Functions { int (* to_func)(GValue *value, PyObject *obj)); int (* value_from_pyobject)(GValue *value, PyObject *obj); PyObject *(* value_as_pyobject)(const GValue *value); + void (* register_interface)(PyObject *dict, const gchar *class_name, + GType (* get_type)(void), + PyExtensionClass *ec); + + void (* register_boxed)(PyObject *dict, const gchar *class_name, + GType boxed_type, PyExtensionClass *ec); + PyObject *(* boxed_new)(GType boxed_type, gpointer boxed, + gboolean copy_boxed, gboolean own_ref); }; #ifndef _INSIDE_PYGOBJECT_ @@ -51,6 +69,7 @@ struct _PyGObject_Functions *_PyGObject_API; #define pyg_boxed_register (_PyGObject_API->boxed_register) #define pyg_value_from_pyobject (_PyGObject_API->value_from_pyobject) #define pyg_value_as_pyobject (_PyGObject_API->value_as_pyobject) +#define pyg_register_interface (_PyGObject_API->register_interface) #define init_pygobject() { \ PyObject *gobject = PyImport_ImportModule("gobject"); \ |
