A special kind of abstract base class - will that work ?

Hello,
With depikt, my python wrappers for gtk i am working at now, i posed a cry of help here, which wasn't needed anymore some days later (but perhaps any kind of utterance was indispensable for continuing). The problem is to represent gtk's kind of "class hierarchy" in Python. This here is my solution, it seems to work and given this is stable it will be the final version.
depikt uses one abstract base class Pikt. Pikt is nothing than its instance and its type struct - and that is the point of my question. As follows:
typedef struct { PyObject_HEAD PyObject *gobj; } Pikt; static PyTypeObject Pikt_Type = { PyVarObject_HEAD_INIT(NULL, 0) "depikt.Pikt", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, };
That is all concerning Pikt. gobj is there to contain the PyCapsules, which itself contain the gtk-pointers to the widgets, created by the following preprocessor factory:
#define KT__GOB_HEADER(YYY, newfunc)
typedef struct { Pikt Q; } YYY;
static PyTypeObject YYY##_Type;
PyObject *YYY##_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
YYY *self; self = (YYY *)type->tp_alloc(type, 0);
self->Q.gobj = PyCapsule_New(newfunc, #YYY, NULL);
if (! self->Q.gobj) { Py_DECREF(self); KTERR("Cannot create "#YYY);};
Py_INCREF(self); return (PyObject *)self;
};
#define KT__GOB_TYPE(XXX)
void XXX##_free(XXX *self)
{ PyObject_Del(self); };
void XXX##_dealloc(XXX *self)
{ Py_XDECREF(self); g_free((gpointer)self->Q.gobj); XXX##_free(self); };
static PyTypeObject XXX##_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"depikt."#XXX,
sizeof(XXX)+4*sizeof(NULL),
0,
(destructor)XXX##_dealloc,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
0,
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
"Python type object for "#XXX,
0, 0, 0, 0, 0, 0,
XXX##_methods,
0, 0,
&Pikt_Type,
0,
0, 0,
-4*sizeof(NULL),
0, 0,
XXX##_new,
(freefunc)XXX##_free,
};
The headers are only for those widgets, for which literally constant newfuncs can be provided (like gtk_window_new(GTK_WINDOW_TOPLEVEL).
(Besides: I am still unsure, whether the dealloc/free couple is right here).
All widgets shall also consist only of the gtk-pointers returned from those newfuncs and method tables - no attributes. The intermediate abstract widgets as GtkContainer are realized as method bundles getting added to each concrete widget's method table by the preprocessor.
Pikt is indsipensable as the argument type for
depikt_Container_add(Pikt *self, Pikt *to_add)
for example. Thus this abstract class is not there for providing a protocol, but as kind of stub for the type system. It is not exposed to Python and actually no proper class.
This looks very clean and petty to me - still i am amazed to have found this. It might even be useful as a design pattern for other extensions (thus i hope, you do not feel like wasting your time reading this). But this goes far beyond of what is teached in the Python tutorials and for me a painful doubt is remaining, whether Pikt as this will really always work.
C combined with inheritance by casting itself and the Python C-API even more have so terrible side effects of allocation strategies. All the more, as i still produce bad programming errors - this solution has by no means solved all my problems with depikt (this is my first ambitious C-project). But already depikt has features pygtk has not.
In this form my question is probably not decidable, but still i'd like to have an estimation of the involved risks doing it like this.
Thanks for reading, Joost
participants (1)
-
Joost