inheriting from C types

Alex Martelli aleax at aleax.it
Wed Jul 17 04:30:32 EDT 2002


Renzo Tomaselli wrote:

> Hi all,
> I'm looking at tips & tricks about inheriting from a C type. It works
> (almost), but from any derived class I'm not able to see any base
> class method.
> Say I implemented a C-type "ype" having
> Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE flags as well as tp_dealloc,
> tp_getattr slots.
> Allocators, constructors etc. are usual defaults.

But how is the tp_methods slot set?

> Now, in Python:
> 
> import ype
> class k(ype.ype):
> pass
> k1 = k()
> 
> I cannot see/invoke any method on base class ype from k1, while I can
> see all of them after direct creation of a base instance, say k2 =
> ype.ype().

That's strange.  Try something like this (inhe.c):


#include "Python.h"

typedef struct {
    PyObject_HEAD
} inhe;

static void
inhe_dealloc(PyObject *op)
{
    op->ob_type->tp_free(op);
}

static PyObject *
inhe_greet(PyObject *self)
{
    Py_INCREF(Py_None);
    return Py_None;
}

static PyMethodDef inhe_methods[] = {
    {"greet", (PyCFunction)inhe_greet, METH_NOARGS},
    {NULL,  NULL}           /* sentinel */
};

static PyTypeObject inhe_t = {
    PyObject_HEAD_INIT(0)
    0,
    "inhe",
    sizeof(inhe),
    0,
    inhe_dealloc,
    0,
    0,
    0,
    0,                                  /* tp_compare */
    0,                                  /* tp_repr */
    0,                                  /* tp_as_number */
    0,                                  /* tp_as_sequence */
    0,                                  /* tp_as_mapping */
    0,                                  /* tp_hash */
    0,                                  /* tp_call */
    0,                                  /* tp_str */
    0,                                  /* tp_getattro */
    0,                                  /* tp_setattro */
    0,                                  /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    "inheritable type",
    0,                                  /* tp_traverse */
    0,                                  /* tp_clear */
    0,                                  /* tp_richcompare */
    0,                                  /* tp_weaklistoffset */
    0,                                  /* tp_iter */
    0,                                  /* tp_iternext */
    inhe_methods,                       /* tp_methods */
    0,                                  /* tp_members */
    0,                                  /* tp_getset */
    0,                                  /* tp_base */
    0,                                  /* tp_dict */
    0,                                  /* tp_descr_get */
    0,                                  /* tp_descr_set */
    0,                                  /* tp_dictoffset */
    0,                                  /* tp_init */
    PyType_GenericAlloc,                /* tp_alloc */
    PyType_GenericNew,                  /* tp_new */
    _PyObject_Del,                      /* tp_free */
};

static PyMethodDef no_methods[] = { {0} };

void
initinhe(void)
{
    PyObject* self;
    inhe_t.ob_type = &PyType_Type;
    self = Py_InitModule("inhe", no_methods);
    PyObject_SetAttrString(self, "inhe", (PyObject*)&inhe_t);
}



and of course the usual setup.py:


from distutils.core import setup, Extension

setup(name = "inhe",
    version = "1.1",
    description = "a tiny example of inheritable type",
    maintainer = "Alex Martelli",
    maintainer_email = "aleaxit at yahoo.com",
       
    ext_modules = [ Extension('inhe', sources=['inhe.c']) ]
)


and a try.py something like:


import inhe

class gop(inhe.inhe): pass

g = gop()
g.pop=23
print g.pop
print g.greet()
del g
i = inhe.inhe()
print i.greet()
print 'OK'

class fop(gop): pass

print dir(inhe.inhe)
print dir(gop)



This is working fine for me with Python 2.2.1.  Maybe it
can help you pinpoint the differences between my working
code and your failing code?


Alex




More information about the Python-list mailing list