Overriding GObject methods in Python



I'd like to design GObject classes so that they can be inherited, and
their methods overriden, from Python.  (See http://tinyurl.com/yfrxtx
for some details and general questions about subclassing GObject classes
from Python.)  GObject being in theory binding-friendly, one would hope
for this to be a straightforward task.  It turns out that things are not
that simple, though.

Gobject virtual methods, in their classic form, are nothing other than
function pointer entries in an improvised vtable contained in the
gobject's class structure.  For example:

typedef struct {
  /* Methods: */
  void (*foo) (Xyz *, int, int);
  bool (*test_bar) (const Xyz *);
  /* ... */
} XyzClass;

void xyz_foo (Xyz *self, int param1, int param2) {
  XYZ_GET_CLASS (self)->foo (self, param1, param2);
}
bool xyz_bar (const Xyz *self) {
  return XYZ_GET_CLASS (self)->bar (self, param1, param2);
}
/* ... */

Subclasses of XyzClass are expected to copy XyzClass's class definition
to their own XyzChildClass structures, and override the fields as
necessary.  That way functions like xyz_foo end up calling the correct
(most specific) virtual method appropriate for the run-time type of
SELF, with no more overhead than a pointer indirection.

The problem is that the fields of XyzClass and its descendants are C
struct members, as inaccessible to Python code as any field of a C
struct, at least without heavy ctypes hackery.  The question is how to
design Xyz and XyzClass to make it amenable to overriding from Python
without a serious performance loss.

One option would be to represent methods as properties whose values are
poiners to GClosure.  Class initialization would set the appropriate
closure properties (this can be done from Python), and the property
change notification cuold be used to cache the property lookup and store
the closure pointer directly into the C structure.  That way the
implementation of public virtual methods remains exactly as shown above,
and Python code gets the option to override methods.

The problem with this approach is that properties are per-object,
whereas methods are per-class.  Python class initialization couldn't
simply set the property associated with the method to a Python method
(represented as GClosure * at the C level) because properties are set on
specific instances, and there are (yet) no instances when the class
object is being initialized.  Even if we had an instance handy, the
property should still be visible to *all* instances of a given class.

Another option would be to forego properties and use a separate vtable
object in the class structure.  The object would encapsulated the
binding of slot to GClosure, and could be exported to Python.  It seems
like reinventing the wheel, though.

Are there existing GObject programs that have tackled this problem?





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]