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

Alex cut_me_out at hotmail.com
Mon Jun 5 17:52:44 EDT 2000


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;
}

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



More information about the Python-list mailing list