PyObject_New not running tp_new for iterators?

Discussion in 'Python' started by Gregory Bond, Apr 20, 2005.

  1. Gregory Bond

    Gregory Bond Guest

    I'm trying to extend Python with an iterator class that should be
    returned from a factory function.

    For some reason the iterator object is not being properly initialised if
    the iterator is created in a C function. It works just fine if the
    object is created using the class contructor

    Trying to minimise the cut-n-paste, but:

    > typedef struct {
    > PyObject_HEAD
    >
    > int i;
    >
    > } MyIter;
    >
    >
    > static PyObject *
    > MyIter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    > {
    > MyIter *self;
    >
    > self = (MyIter *)type->tp_alloc(type, 0);
    > if (self) {
    > self->i = 0;
    > }
    >
    > return (PyObject *)self;
    > }
    >
    > static PyObject *
    > MyIter_Iter(PyObject *self)
    > {
    > Py_INCREF(self);
    > return self;
    > }
    >
    > static PyObject *
    > MyIter_Next(PyObject *self)
    > {
    > MyIter *ep = (MyIter *) self;
    > return Py_BuildValue("i", ep->i++);
    > }



    plus the usual type stucture. This simple iterator returns the integers
    from 0 to (programmer's) infinity.

    This works fine if I create the object directly:

    > Python 2.3.1 (#3, Oct 1 2003, 16:18:11)
    > [GCC 3.3] on sunos5
    > Type "help", "copyright", "credits" or "license" for more information.
    >>>> import myiter
    >>>> e = myiter.MyIter()
    >>>> str(e)

    > '<myiter.MyIter object at 0x184050>'
    >>>> e.next()

    > 0
    >>>> e.next()

    > 1
    >>>> e.next()

    > 2
    >>>> e.next()

    > 3


    However, if I create the MyIter object from a C factory function:

    > static PyObject *
    > FromFile(PyObject *self, PyObject *args)
    > {
    > MyIter *ro;
    >
    > if (!PyArg_ParseTuple(args, ""))
    > return NULL;
    >
    > if (!(ro = PyObject_New(MyIter, &MyIterType)))
    > return NULL;
    >
    > return (PyObject *)ro;
    > }
    >
    > static PyMethodDef My_methods[] = {
    > {"FromFile", FromFile, METH_VARARGS,
    > "Return an iterator."},
    > {NULL} /* Sentinel */
    > };


    then the MyIter object is not properly initialised!

    >>>> f = myiter.FromFile()
    >>>> f

    > <myiter.MyIter object at 0x184070>
    >>>> f.next()

    > -2080374694
    >>>> f.next()

    > -2080374693
    >>>> f.next()

    > -2080374692
    >>>>


    I tried a similar problem with a plane-old-object using tp_members
    (rather than an iterator object) and that worked fine, even from a
    factory function.

    I've looked long and hard at the API doc, but I'm stumped..... I've
    checked a couple of examples and they just do what I'm doing!

    What am I missing?
    Gregory Bond, Apr 20, 2005
    #1
    1. Advertising

  2. Gregory Bond

    Gregory Bond Guest

    I wrote:

    [snip]

    > What am I missing?


    The fundamental problem is that this:

    >> if (!(ro = PyObject_New(MyIter, &MyIterType)))
    >> return NULL;


    is really only a malloc() - it doesn't call the tp_new function at all.
    This is not really clear in the 2.3 version of the C API document that
    I was consulting - the 2.4 version is much clearer.

    I have no idea how to do in C all the things that calling a class
    constructor in Python does. Am I supposed to be calling tp_new &
    tp_init directly?

    In the end, this particular class really only needs to be created from a
    factory function, so I removed the tp_new member altogether and just
    wrote a C function to initialise the object, and called that from the C
    factory function.

    [The above is not particular to the fact that my class is an iterator -
    all C classes have the same behaviour. My test of a plain-old class
    probably looked like it worked due to lucky memory patterns.]
    Gregory Bond, Apr 21, 2005
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Marcin Kaliciñski

    Iterators and reverse iterators

    Marcin Kaliciñski, May 8, 2005, in forum: C++
    Replies:
    1
    Views:
    478
    Kai-Uwe Bux
    May 8, 2005
  2. Jeremy Moles

    PyObject_New

    Jeremy Moles, Oct 6, 2005, in forum: Python
    Replies:
    2
    Views:
    1,339
    Jeremy Moles
    Oct 7, 2005
  3. =?ISO-8859-1?Q?Gerhard_H=E4ring?=

    Re: PyObject_New

    =?ISO-8859-1?Q?Gerhard_H=E4ring?=, Oct 7, 2005, in forum: Python
    Replies:
    0
    Views:
    368
    =?ISO-8859-1?Q?Gerhard_H=E4ring?=
    Oct 7, 2005
  4. Replies:
    1
    Views:
    616
    Gabriel Genellina
    May 18, 2007
  5. Michael Hennebry

    tp_new, tp_alloc, tp_init

    Michael Hennebry, Nov 30, 2011, in forum: Python
    Replies:
    1
    Views:
    372
    Gregory Ewing
    Dec 8, 2011
Loading...

Share This Page