[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