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

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.

#include "Python.h"
#include "arrayobject.h"
#include <assert.h>

void *die (PyObject *exception, char *error_message) {
    PyErr_SetString (exception, error_message);
    return NULL;

Quote:
}

void *die_value (char *error_message) {
    return die (PyExc_ValueError, error_message);

Quote:
}

void *die_system (char * error_message) {
    return die (PyExc_SystemError, error_message);

Quote:
}

PyObject *None () {
    Py_INCREF (Py_None);
    return Py_None;

Quote:
}

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;

Quote:
}

void PyArrayObject_Print (PyArrayObject *array) {
  PyObject_Print ((PyObject *)array, stdout, 0);
  printf ("\n");

Quote:
}

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 ();

Quote:
}

static PyMethodDef my_arrays_methods[] = {
  {"inc", my_arrays_inc, METH_VARARGS},
  {NULL, NULL} /* Marked as "Sentinel" in manual. */

Quote:
};

void initmy_arrays () {
  (void) Py_InitModule ("my_arrays", my_arrays_methods);
Quote:
}



Fri, 22 Nov 2002 03:00:00 GMT  
 C extension using Numeric arrays -- do I really need all this error

Quote:

> 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.
Quote:
> #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);
> }

  12klat.vcf
< 1K Download


Sat, 23 Nov 2002 03:00:00 GMT  
 C extension using Numeric arrays -- do I really need all this error

Quote:
> 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.

Yes, I fully agree, but I'm really asking if there is some way to make
the Numeric extension handle some of the prissiness for me.

Spoiled-by-python,-perhaps-'ly yrs
Alex.



Sat, 23 Nov 2002 03:00:00 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. Doing assembly and really doing assembly

2. Doing assembly and really doing assembly

3. Returning a lot of data from a c extension (SWIG,array, Numeric)

4. ANNOUNCE: narray, a numeric array extension for Tcl

5. Max Size of Array when using Numeric.py

6. Using Numeric arrays to store different datatypes

7. Convert 1D string Array to Numeric Array

8. ARRAY[NUMERIC] := ARRAY[DOUBLE] -- where?

9. Numeric 2d Array to 3d Array

10. GAWK: Question on using filefuncs.so (creating arrays in extension functions)

11. Tutorial on using NumPy arrays in C extension modules

12. Need Help with Numerical-Python array extension

 

 
Powered by phpBB® Forum Software