[Tutor] Extensions in C - numeric arrays & pointers

Reggie Dugard reggie@merfinllc.com
Fri Mar 14 13:50:03 2003


Scott,

I think the mystery you're looking for is PyArray_ContiguousFromObject.

There's a short tutorial on NumPy array in C extensions at 

http://starship.python.net/crew/hinsen/NumPyExtensions.html

that I think you'll find helpful.  Modifying your example to use this,
it would look something like:


static PyObject *
ezmath_average(PyObject *self, PyObject *args)
{
  PyObject *x;
  PyArrayObject *xa;
  double y;

  if (!PyArg_ParseTuple(args, "O", &x))
    return NULL;

  xa = (PyArrayObject *)PyArray_ContiguousFromObject(x, PyArray_DOUBLE, 1, 1);
  if (xa == NULL)
    return NULL;
 
  y = average(xa->data, xa->dimensions[0]);

  return PyFloat_FromDouble(y);
}


On Fri, 2003-03-14 at 09:53, Ray, Scott (Dow AgroSciences) wrote:
> As part of my Python education, I decided to turn a handful of simple numerical C functions into a small Python extension.  I first selected a simple C function that takes one scalar input (a float or a double) and returns one scalar output (same).  I followed the guidance in Guido and Drake's  "Extending and Embedding" guide and, much to my delight, the extension worked on the first try.
> 
> Then I moved to C functions that work with numeric arrays and their associated pointers.  This has not gone so smoothly.  After much experimentation, re-reading of documentation, searching mailing list archives, and scanning through other people's source code, I'm still stuck and in need of some guidance.  So, I now turn to the experts.
> 
> Here's a simple C function that is representative of what I'm trying to work with.
> 
> 	double average(double *xvec, int numpts) {
> 	  int n;
> 	  double xbar;
> 
> 	  xbar = 0.0;
> 	  for (n = 0; n < numpts; ++n) {
> 	    xbar += xvec[n];
> 	  }
> 	  return xbar/numpts;
> 	}
> 
> Given C's argument passing mechanism (pass by value) , this routine expects its first argument to be a pointer to an array of doubles.
> 
> What I want to be able to do is include this C function in a Python extension module (call it "ezmath") and use it in Python as:
> 
> 	import ezmath
> 	z = [3.1416, 2.71828, 42]
> 	ezmath.average(z,3)
> 
> I'm thinking that the C wrapper function should look something like,
> 
> 	static PyObject *
> 	ezmath_average(PyObject *self, PyObject *args) {
> 		PyObject *x;
> 		int num;
> 		double *xa;
> 		double y;
> 
> 		if (!PyArg_ParseTuple(args, "Oi", &x, &num)) {
> 			return NULL;
> 		}
> 
> 		/* big mystery here */
> 
> 		y = average(xa, num);
> 		return Py_BuildValue("d",y);
> 	}

Good Luck!
-- 
Reggie Dugard <reggie@merfinllc.com>
Merfin, LLC