#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]
>>>