C extension using Numeric arrays -- do I really need all this error

Ken Seehof 12klat at sightreader.com
Tue Jun 6 07:39:29 EDT 2000



Alex wrote:

> Hi.  I wrote a simple C extension using Numeric arrays today.  It takes
> an integer array and the coordinates of an element in that array, and
> increments it by one.  The code is below, if anyone's interested.
>
> I was wondering, do I really have to be so prissy about error checking?
> Is there anything I can do to make Numeric do more of the work?
>
> Alex.

In general it is a good idea to be very prissy about error checking.  In particular, it should be
impossible to crash an extension module, or corrupt memory, no matter how hard you try from
python.

> #include "Python.h"
> #include "arrayobject.h"
> #include <assert.h>
>
> void *die (PyObject *exception, char *error_message) {
>     PyErr_SetString (exception, error_message);
>     return NULL;
> }
>
> void *die_value (char *error_message) {
>     return die (PyExc_ValueError, error_message);
> }
>
> void *die_system (char * error_message) {
>     return die (PyExc_SystemError, error_message);
> }
>
> PyObject *None () {
>     Py_INCREF (Py_None);
>     return Py_None;
> }
>
> long offset (int dimension, int *strides, PyObject *coordinates) {
>   long int answer = 0, dimension_index;
>   PyObject *coordinate;
>   assert ((PySequence_Check (coordinates)) &&
>           (PySequence_Length (coordinates) == dimension));
>   for (dimension_index = 0; dimension_index < dimension; dimension_index++) {
>     coordinate = PySequence_GetItem (coordinates, dimension_index);
>     answer += strides[dimension_index] * PyInt_AsLong (coordinate);
>   }
>   return answer;
> }
>
> void PyArrayObject_Print (PyArrayObject *array) {
>   PyObject_Print ((PyObject *)array, stdout, 0);
>   printf ("\n");
> }
>
> static PyObject *my_arrays_inc (PyObject *self, PyObject *args) {
>   PyObject *indices, *increment;
>   PyArrayObject *array;
>   int dimension_index, cell_offset, coordinate;
>
>   if (!PyArg_ParseTuple(args, "O!O", &PyArray_Type, &array, &indices)) {
>     return NULL;
>   }
>
>   if (array->descr->type_num != PyArray_INT) {
>     return die_value ("Array must be of type int");
>   }
>
>   if (!PySequence_Check (indices)) {
>     return die_value ("Second argument should be a sequence.");
>   }
>
>   for (dimension_index = 0; dimension_index < PySequence_Length (indices);
>        dimension_index++) {
>     if (!PyInt_Check (PySequence_GetItem (indices, dimension_index))) {
>       return die_value ("Second argument should be a sequence of integers.");
>     }
>   }
>
>   if (array->nd != PySequence_Length (indices)) {
>     return die_value ("Length of indices must correspond to dimension of array.");
>   }
>
>   for (dimension_index = 0; dimension_index < array->nd; dimension_index++) {
>     coordinate = PyInt_AsLong (PySequence_GetItem (indices, dimension_index));
>     if ((coordinate < 0) || (array->dimensions[dimension_index] <= coordinate))  {
>       return die (PyExc_IndexError,
>                   "Values in indices must be nonegative and less than corresp. dimensions.");
>     }
>   }
>
>
>   cell_offset = offset (array->nd, array->strides, indices);
>   (int)(array->data[cell_offset]) += 1;
>
>   return None ();
> }
>
> static PyMethodDef my_arrays_methods[] = {
>   {"inc", my_arrays_inc, METH_VARARGS},
>   {NULL, NULL} /* Marked as "Sentinel" in manual. */
> };
>
> void initmy_arrays () {
>   (void) Py_InitModule ("my_arrays", my_arrays_methods);
> }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 12klat.vcf
Type: text/x-vcard
Size: 343 bytes
Desc: Card for Ken Seehof
URL: <http://mail.python.org/pipermail/python-list/attachments/20000606/7b09173a/attachment.vcf>


More information about the Python-list mailing list