PyObject_New not running tp_new for iterators?
Gregory Bond
gnb at itga.com.au
Wed Apr 20 04:11:12 EDT 2005
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?
More information about the Python-list
mailing list