473,399 Members | 3,656 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

question: numarray c extension error handling?

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.");

/* Align, Byteswap, Contiguous, Typeconvert */
kernel = NA_IoArray(okernel, tFloat64, C_ARRAY);
....
if (!kernel...)
return PyErr_Format( _convolveError,
"Convolve1d: error converting array inputs.");
....
Py_XDECREF(kernel);
....
}

The relevant section of the docs (section 12.3 High-level API):

The return value of each function (NA_InputArray, NA_OutputArray, or
NA_IoArray) is either a reference to the original numarray object, or a
reference to a temporary numarray. Following execution of the C-code in
the extension function body this pointer should *always* be DECREFed.
Jul 18 '05 #1
8 1784
At some point, "Russell E. Owen" <no@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
Jul 18 '05 #2
In article <qn*************@arbutus.physics.mcmaster.ca>,
co**********@physics.mcmaster.ca (David M. Cooke) wrote:
...
/* 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.


I'm afraid I was too selective in extracting code, making it look like
no DECREF was even wanted. Here is a more complete extract. The first
test can fail even if one or two of the arrays was successfullly
"extracted", so a DECREF is wanted then, and all the more so for the two
tests after that:

....
/* Align, Byteswap, Contiguous, Typeconvert */
kernel = NA_IoArray(okernel, tFloat64, C_ARRAY);
data = NA_IoArray(odata, tFloat64, C_ARRAY);
convolved = NA_OptionalOutputArray(oconvolved, tFloat64, C_ARRAY,
data);

if (!kernel || !data || !convolved)
return PyErr_Format( _convolveError,
"Convolve1d: error converting array inputs.");

if ((kernel->nd != 1) || (data->nd != 1))
return PyErr_Format(_convolveError,
"Convolve1d: numarray must have 1 dimensions.");

if (!NA_ShapeEqual(data, convolved))
return PyErr_Format(_convolveError,
"Convolve1d: data and output numarray need identitcal
shapes.");

Convolve1d(kernel->dimensions[0],
NA_OFFSETDATA(kernel),
data->dimensions[0],
NA_OFFSETDATA(data),
NA_OFFSETDATA(convolved));

Py_XDECREF(kernel);
Py_XDECREF(data);
....

It sounds as if I should submit a bug report on the example.

-- Russell
Jul 18 '05 #3
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 <qn*************@arbutus.physics.mcmaster.ca>,
co**********@physics.mcmaster.ca (David M. Cooke) wrote:
At some point, "Russell E. Owen" <no@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.
Jul 18 '05 #4
At some point, Lou Pecora <pe****@anvil.nrl.navy.mil> wrote:
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. :-)


Not a problem; I wish more people would :-)

--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
Jul 18 '05 #5
It is arbitrarily trivial to convert it to use an error boolean.

- Josiah

static PyObject * Py_Convolve1d(PyObject *obj, PyObject *args)
{
PyObject *okernel,...;
PyArrayObject *kernel = NULL;
bool error = 0;

if (!PyArg_ParseTuple(args, "OO|O", &okernel, ...)) {
PyErr_Format(_convolveError,
"Convolve1d: Invalid parameters.");
error = 1;
}
kernel = NA_IoArray(okernel, tFloat64, C_ARRAY);
if (!kernel...) {
PyErr_Format( _convolveError,
"Convolve1d: error converting array inputs.");
error = 1;
}

...more stuff...

if (!error) {
Py_XDECREF(kernel)
return the result
} else {
Py_XDECREF(kernel)
return NULL;
}
}
Jul 18 '05 #6
In article <c2**********@news.service.uci.edu>, Josiah Carlson wrote:
It is arbitrarily trivial to convert it to use an error boolean.
No, it isn't, as evidenced by the fact that you did it wrong.
static PyObject * Py_Convolve1d(PyObject *obj, PyObject *args)
{
PyObject *okernel,...;
PyArrayObject *kernel = NULL;
bool error = 0;

if (!PyArg_ParseTuple(args, "OO|O", &okernel, ...)) {
PyErr_Format(_convolveError,
"Convolve1d: Invalid parameters.");
error = 1;
}
if (!error) { kernel = NA_IoArray(okernel, tFloat64, C_ARRAY);
if (!kernel...) {
PyErr_Format( _convolveError,
"Convolve1d: error converting array inputs.");
error = 1;
} }

if (!error) { ...more stuff... }
if (!error) {
Py_XDECREF(kernel)
return the result
} else {
Py_XDECREF(kernel)
return NULL;
}
}


You have to remember to check the error variable at every step in the
function, or use else clauses and deal with heavy nesting. This is a
perfect situation for GOTO.

Joe
Jul 18 '05 #7
> You have to remember to check the error variable at every step in the
function, or use else clauses and deal with heavy nesting. This is a
perfect situation for GOTO.


I did slip, but it is still fairly easy to do, I just wasn't paying
attention. It does show a situation where GOTO can be useful, I'll give
you that. Depending on the code, it may be a case where a macro would
be better suited.

- Josiah
Jul 18 '05 #8
>>>>> "Josiah" == Josiah Carlson <jc******@nospam.uci.edu> writes:

Josiah> I did slip, but it is still fairly easy to do

This "fairly easy" ignores the possibility that later you need to add or
modify the line that must be executed before the function returns. Macro
might be a solution, although I consider the goto solution cleaner (doesn't
need a separate language (and thus different indentation rules), won't
pollute the namespace, ease the compiler to reduce compiled code size, etc).

Regards,
Isaac.
Jul 18 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: RJS | last post by:
Hi all, I can't get a py2exe compiled app to run with numarray (numarray-0.5.win32- py2.2). Also wxPythonWIN32-2.3.3.1-Py22 and ActivePython-2.2.1-222. In the sample below, commenting out...
3
by: Alexander Schwaigkofler | last post by:
Hi! I have the following problem with numarray. I read the install.txt manual, but it doesn't already work. OS: Microsoft Windows 2000 python: Python 2.2.3 (#42, May 30 2003, 18:12:08) on...
4
by: Marco Bubke | last post by:
Hi I have tried to include numarray in Pyrex but I get allways this error: Traceback (most recent call last): File "gears.py", line 9, in ? import gl File...
2
by: Marc Schellens | last post by:
Following the NumPy documentation, I took over some C code, but run into an error. Does anybody have a suggestion? Thanks, marc gdlpython.cpp:225: `PyArray_Type' undeclared (first use this...
3
by: SunX | last post by:
I tried to initialize a float point array by: import numarray xur = numarray.fromfunction(lambda x,y,z:x*y*z, (2, 2, 2)) but I ended up with an integer array even though x, y, and z are all...
11
by: grv | last post by:
So it is supposed to be very fast to have an array of say 5 million integers stored in a binary file and do a = numarray.fromfile('filename', (2, 2, 2)) numarray.add(a, 9, a) but how is that...
2
by: maxwell | last post by:
I'm trying to use the 'numarray' package (v1.1.1) under Python 2.4 running under CygWin. I initially downloaded the Windows executable version of the numarray package, and installed it under...
3
by: PL | last post by:
I want to pass a 2D array from Python to C++, manipulate it in C++ (for example, add 1 to each element) and pass it back to Python. With these building blocks I will be able to figure out all the...
11
by: Trent | last post by:
Running this I see that on first run, both bubble and selection sort have 9 sort counts while insertion sort has ZERO. With a sorted list, should this be ZERO for all? Also bsort and Ssort have...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.