A GOTO example (was question: numarray c extension...)
Lou Pecora
pecora at anvil.nrl.navy.mil
Thu Mar 11 15:41:21 EST 2004
Here's a nice use of goto's in a Python C extension for those who have
been following the goto thread. I like it (see code at end and the nice
resolve for returns the goto's give). I hope Mr. Cooke does not mind me
"borrowing" his code. :-)
In article <qnksmggs6uh.fsf at arbutus.physics.mcmaster.ca>,
cookedm+news at physics.mcmaster.ca (David M. Cooke) wrote:
> At some point, "Russell E. Owen" <no at spam.invalid> wrote:
>
> > I'm writing a C extension for numarray and am puzzled about the idiom
> > for error handling.
> >
> > The documentation seems to say one should always decref an array after
> > calling NA_InputArray, etc., to convert numarray args to C arrays.
> >
> > However, the example and also the numarray code suggests that it's OK to
> > return early via (for example) PyErr_Format without doing the DECREF.
> > For example, I have appended a very abbreviated version of the sample
> > code.
> >
> > Comments? I'll plow ahead and follow the example (i.e. with early
> > return) but I was wondering if anyone knew why this was OK. Perhaps I
> > should put in a request to the numarray project for a clarification in
> > the documentation.
> >
> > -- Russell
> >
> > static PyObject * Py_Convolve1d(PyObject *obj, PyObject *args)
> > {
> > PyObject *okernel,...;
> > PyArrayObject *kernel...;
> >
> > if (!PyArg_ParseTuple(args, "OO|O", &okernel, ...))
> > return PyErr_Format(_convolveError,
> > "Convolve1d: Invalid parameters.");
>
> This is ok; if PyArg_ParseTuple is NULL, no objects are created (or
> INCREF'd). Also, if it's not NULL, okernel is a borrowed reference;
> you shouldn't DECREF it.
>
> >
> > /* Align, Byteswap, Contiguous, Typeconvert */
> > kernel = NA_IoArray(okernel, tFloat64, C_ARRAY);
> > ...
> > if (!kernel...)
> > return PyErr_Format( _convolveError,
> > "Convolve1d: error converting array inputs.");
>
> This is also ok (assuming there is nothing between this and the above
> which makes a reference to objects). If NA_IoArray returns NULL,
> there isn't anything to DECREF.
>
> > ...
> > Py_XDECREF(kernel);
> > ...
> > }
>
> Personally, I write it like this:
>
> static PyObject * Py_Convolve1d(PyObject *obj, PyObject *args)
> {
> PyObject *okernel,...;
> PyArrayObject *kernel = NULL;
>
> if (!PyArg_ParseTuple(args, "OO|O", &okernel, ...)) {
> PyErr_Format(_convolveError,
> "Convolve1d: Invalid parameters.");
> goto error;
> }
> kernel = NA_IoArray(okernel, tFloat64, C_ARRAY);
> if (!kernel...) {
> PyErr_Format( _convolveError,
> "Convolve1d: error converting array inputs.");
> goto error;
> }
>
> ...more stuff...
>
> Py_XDECREF(kernel)
> return the result
> error:
> Py_XDECREF(kernel)
> return NULL;
> }
>
> Notice that kernel was initialized to NULL, so Py_XDECREF will work in
> all cases. Clean error-handling code like this is one of the few
> places I use goto in C. You now have only two exits out of the
> function, at the bottom, and so it's _much_ easier to keep track of
> what needs to be DECREF'd.
-- Lou Pecora
My views are my own.
More information about the Python-list
mailing list