Welcome, guest | Sign In | My Account | Store | Cart
#include "python.h"

extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *));

static PyObject *py_compare_func = NULL;

static int
stub_compare_func(const PyObject **a, const PyObject **b)
{
    int retvalue = 0;

    // Build up the argument list... 
    PyObject *arglist = Py_BuildValue("(OO)", *a, *b);

    // ...for calling the Python compare function.
    PyObject *result = PyEval_CallObject(py_compare_func,arglist);

    if (result && PyInt_Check(result)) {
        retvalue = PyInt_AsLong(result);
    }

    Py_XDECREF(result);
    Py_DECREF(arglist);
    
    return retvalue;
}


static PyObject *pyqsort(PyObject *obj, PyObject *args)
{
    PyObject *pycompobj;
    PyObject *list;
    if (!PyArg_ParseTuple(args, "OO", &list, &pycompobj)) 
        return NULL;
    
    // make sure second argument is a function
    if (!PyCallable_Check(pycompobj)) {
        PyErr_SetString(PyExc_TypeError, "Need a callable object!");
    }
    else {
        // save the compare func. This obviously won't work for multi-threaded
        // programs.
        py_compare_func = pycompobj;
        if (PyList_Check(list)) {
            int size = PyList_Size(list);
            int i;
            
            // make an array of (PyObject *), because qsort does not know about
            // the PyList object
            PyObject **v = (PyObject **) malloc( sizeof(PyObject *) * size );
            for (i=0; i<size; ++i) {
                v[i] = PyList_GetItem(list, i);
                // increment the reference count, because setting the list items below
                // will decrement the ref count
                Py_INCREF(v[i]);
            }
            qsort(v, size, sizeof(PyObject*), stub_compare_func);
            for (i=0; i<size; ++i) {
                PyList_SetItem(list, i, v[i]);
                // need not do Py_DECREF - see above
            }
            free(v);
        }
    }
    Py_INCREF(Py_None);
    return Py_None;
}

static PyMethodDef qsortMethods[] = {
    { "qsort", pyqsort, METH_VARARGS },
    { NULL, NULL }
};

__declspec(dllexport) void initqsort(void) {
    PyObject *m;
    m = Py_InitModule("qsort", qsortMethods);
}


In Python
ActivePython 2.1, build 210 ActiveState)
based on Python 2.1 (#15, Apr 23 2001, 18:00:35) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import qsort
>>> a = [9, 3, 5, 4, 1]
>>> def revcmp(a, b): return cmp(b, a)
...
>>> qsort.qsort(a, revcmp)
>>> a
[9, 5, 4, 3, 1]
>>>

History

  • revision 2 (22 years ago)
  • previous revisions are not available