How Can I Capture the Class Object for a Python Class Derived From My C API Metatype?

Rob Stewart stewart at sig.com
Mon Nov 12 15:08:52 CET 2001


stewart at sig.com (Rob Stewart) wrote in message news:<3a5a7d54.0111091305.70bad186 at posting.google.com>...
> I need to create a metatype, using the C API, that can save the class
> objects for Python classes derived from it.  I need to be able to use
> the class object to instantiate objects of that class under C (C++)
> program control, and to discover the methods that have been defined to
> override default behavior so C++ virtual function calls can be
> forwarded to Python methods.

I should mention that, as I understand it, the common metatype of the
bases of the class declared in Python is called to create the Python
class object.  That means the type of my metatype, which would be the
base for the Python class I wish to capture, is called.  It is the
type of my metatype that then creates the class object for the
declared Python class.  Since I'm sure that's as clear as mud, let me
illustrate:

Let M be my metatype.
Let T be the type of my metatype.
Let P be a Python class.

# Some Python code:
class P(M):
    pass

As I understand the mechanism, T's tp_call slot function is invoked to
instantiate a class object describing P.  If T is PyType_Type, then
tp_call is defined to call the tp_new slot on the type of the new
object, which ultimately should call tp_new on T (since the derived
type's tp_new should call the base's tp_new.  At that point, T can
save the PyObject * for the class object being created for later use
by the C++ code.

At that point, it should, I think, also be possible to capture the
methods implemented or inherited by P.  For each method of an
expected, predetermined name, I can capture the PyObject * for that
method for subsequent invocation by the C++ code.  The notion here, is
that if the method hasn't been overridden, then I can provide the
default behavior in C++ rather than always forwarding to a method in
the metatype.  This is merely a performance optimization.

> My current, flailing (and failing) attempt was to create a metatype,
> for which ob_type is set to the address of a PyTypeObject which starts
> out being a copy (via memcpy()) of PyType_Type.  I set the tp_new slot
> of that type object (the meta-metatype, if you will) to a function
> that can capture the class object and inspect it for methods.  I've
> been tweaking the tp_bases and tp_mro fields of that type object, but
> haven't found the right combination of values to get things working.
> 
> For example, type_new() was complaining at first because my
> meta-metatype wasn't its own supertype.  I tried setting tp_mro to
> NULL, but that wreaked havoc elsewhere.  So, I created a tuple
> containing just the meta-metatype.  That got me farther, but I then
> found that I needed to put &PyType_Type in the tuple.  Unfortunately,
> having done that, I merely stumble upon other problems.
> 
> The point is, the approach I'm taking is a hack, and it's brittle,
> assuming I can even make it work.  That makes it highly undesirable. 
> Hopefully, then, there's a better way to go about this.
> 
> Thanks for any help you can offer.
> 
> Rob



More information about the Python-list mailing list