question: numarray c extension error handling?
David M. Cooke
cookedm+news at physics.mcmaster.ca
Wed Mar 10 16:57:42 EST 2004
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.
--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
More information about the Python-list
mailing list