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