I'm looking into using gobject's OO framework for the low-level portion
of an application, with the intention of using Python for extending and
scripting the low-level functionality.  Ideally, the C code would just
use gobjects and know nothing (or as little as possible) about Python.

While studying PyGobject I stumbled into a subclassing problem.  I'd
like to subclass from Python a gobject class written in C (and itself
derived from GObject), and eventually pass its instances to the C code
that expects regular gobjects.  This would allow Python code to create
first-class GObject classes and objects usable within the framework.

For example:

# MyClass is a gobject class implemented in C.
MyClass = gobject.type_from_name('MyClass')

# Subclass it in Python.
class Foo(MyClass):
  ... additional code here ...
gobject.type_register(Foo)

# From this point, instances of Foo should be GObject type instances
# and therefore first-class citizens in the GObject world.

Let's try it:

[~/work/testgobject]$ python
Python 2.4.4c1 (#2, Oct 11 2006, 21:51:02) 
[GCC 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)] on linux2
[...]
>>> import gobject
>>> import ctypes
>>> ctypes.cdll
# load a pure-C SO that implements a test gobject type, DateTimeType
>>> x=ctypes.cdll.LoadLibrary("./x.so")
>>> x.initialize()   # set up the type
>>> gobject.type_from_name("DateTimeType")
<GType DateTimeType (135936872)>
>>> o=gobject.new(gobject.type_from_name('DateTimeType'))
>>> o
<__main__.DateTimeType object (DateTimeType) at 0xb7d8ac84>

That part works -- the gtype is accessible from Python and appears
usable.  But what if I want to subclass the type?  Since Python 2.4
allows subclassing built-in types, I tried it this way:

>>> class Foo(gobject.type_from_name("DateTimeType")):
...   def foo(self):
...     self
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: Error when calling the metaclass bases
    GType.__init__() takes exactly 1 argument (3 given)

Obviously, this is wrong.  It doesn't make sense to try to subclass the
GType type, we must inherit from a type that can create actual GType
instances.  The distinction is subtle, but very important, as shown
here:

>>> gobject.type_from_name('GObject')
<GType GObject (80)>                         # (1)
>>> gobject.type_from_name('DateTimeType')
<GType DateTimeType (135936872)>             # (2)
>>> gobject.GObject
<type 'gobject.GObject'>                     # (3)

To inherit from DateTimeType, I need to get a Python type object like
(3), not a GType type object, like (1) or (2).  But hey, I already have
a Python *instance* of DateTimeType, so the type must be accessible as
well:

>>> type(o)
<class '__main__.__main__.DateTimeType'>

If it's a class object, it must be subclassable:

>>> class Foo(type(o)):
...   def foo():
...     return self
... 
>>> foo=Foo()
>>> foo
<Foo object (DateTimeType) at 0xb7d8fd74>

But Foo is still not a separate GObject class; for GObject code, a Foo
object is indistinguishable from a DateTimeType object:

>>> gobject.type_name(type(foo))
'DateTimeType'

To fix that, we must register it with GType:

>>> gobject.type_register(Foo)
<class '__main__.Foo'>
>>> gobject.type_name(type(foo))
'__main__+Foo'

Instances of Foo are now not only first-class citizens of the GObject
world, but GObject is also aware of the inheritance relationship between
DateTimeType and Foo:

>>> gobject.type_children(gobject.type_from_name('DateTimeType'))
[<GType __main__+Foo (136049464)>]

In conclusion, it would seem that PyGTK's gobject wrapper has all the
pieces needed for this, with the following parts being (to me)
non-obvious:

1. What is the canonical way to convert <GType x> to something like
<class 'x'> as shown above?  Creating an instance of x and calling
type(x) seems like an incredible kludge.

2. Has anyone tried to pass GObjects created in a similar way back to C?
How does one convert a PyObject* to a GObject*?

3. Is it intended to be able to subclass gobject classes other than
GObject?  All the examples I can find only demonstrate subclassing
gobject.GObject and its Python class children.

I would appreciate any help with this.  If this is described in a
publicly accessible document, feel free to point it out.



_______________________________________________
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to