tiny extension crashes

John J. Lee phrxy at csv.warwick.ac.uk
Wed Mar 14 15:49:06 EST 2001


I've been using a tiny little C extension module that I wrote for a while
now, and haven't had any trouble.  Just recently, I've been getting
crashes which go away when I use my pure Python implementations of these
functions.  I only get these crashes on windows (mingw32 compiler), not on
linux.  The other odd thing is that either of the two functions in the
extension seem to trigger the crashes on their own (or both together).
As far as I can see there is no need for any Py_INCREF or Py_DECREFfing in
these functions, but these are my first extensions, so I may be mistaken.

Can anyone help out, or tell me where to start looking?

Here is the whole C extension source file:



#include <Python.h>
#include "Numeric/arrayobject.h"

/* Non-Python functions
   ie, not callable from python. */

static int array_max(PyArrayObject *array, int absolute) {
    /* Return maximum of an integer multiarray */
    int i, max, elem = 0;
    for(i=0, max=0; i < array->dimensions[0]; i++) {
        elem = *(long *)(array->data + i*array->strides[0]);
        if (absolute)
            elem = fabs(elem);
        if (elem > max)
            max = elem;
    }
    return max;
}

/* Python functions */

static PyObject *iround(PyObject *self, PyObject *args) {
    /* round to integer type, 0.49->0, 0.5->1 */
    double number;
    double *intp;

    if (!PyArg_ParseTuple(args, "d", &number))
        return NULL;
    if (fabs(modf(number, intp)) >= 0.5) {
        *intp >= 0 ? (*intp)++ : (*intp)--;
    }
    return Py_BuildValue("l", (long)*intp);
}

static PyObject *hcf(PyObject *self, PyObject *args) {
    /* return highest common factor of a 1D numpy array
       XXX this algorithm is probably the worst possible
       XXX also probably needs to take general sequence arguments */
    PyArrayObject *array;
    long i, n, factor = 0, elem;
    long length;
    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &array))
        return NULL;
    if (array->nd != 1 || (array->descr->type_num != PyArray_SHORT &&
                           array->descr->type_num != PyArray_LONG)) {
        PyErr_SetString(PyExc_TypeError,
                        "array must be 1D and of integer type");
        return NULL;
    }
    if ((length = array->dimensions[0]) == 0) {
        PyErr_SetString(PyExc_ValueError, "array must not be of zero length");
        return NULL;
    }
    /* start at highest element and count down to 1 */
    for (n=array_max(array, 1); n > 0; n--) {
        /* is it a factor of all the rest? */
        factor = n;
        for (i=0; i < length; i++) {
            elem = *(long *)(array->data + i*array->strides[0]);
            if (elem % n != 0) {
                factor = 0;
                break; /* not a factor, try n-1 */
            }
        }
        if (factor) break; /* found hcf */
    }
    return Py_BuildValue("l", (long)factor);
}

/* Boilerplate */

static PyMethodDef cutils_methods[] = {
    {"iround", iround, METH_VARARGS},
    {"hcf", hcf, METH_VARARGS},
    {NULL, NULL}
};

void initcutils(void) {
    (void) Py_InitModule("cutils", cutils_methods);
    import_array()
}


-- 
John




More information about the Python-list mailing list