One of the developer technologies introduced in Snow Leopard is an extension to C/Objective-C called “blocks”, which adds anonymous (lambda) functions to the language. If you’re not yet familiar with blocks, I recommend Mike Ash’s excellent introduction to the subject.

Unfortunately for developers targeting platforms other than 10.6 (including the iPhone), support for blocks in not available from Apple. There is an alternative, however, thanks to the clever folks at Plausible Labs in the form of Plausible Blocks:

Plausible Blocks (PLBlocks) provides a drop-in runtime and toolchain for using blocks in iPhone 2.2+ and Mac OS X 10.5 applications. Both the runtime and compiler patches are direct backports from Apple’s Snow Leopard source releases.

PLBlocks is great, but one thing it can’t provide is block support in common libraries, as is found in Snow Leopard. For example, the qsort standard library function has a qsort_b variant under Snow Leopard that allows passing a block instead of a function pointer for the comparison operator. From the man pages:

The heapsort_b(), mergesort_b(), and qsort_b() routines are like the corresponding routines without the _b suffix, expect [sic] that the compar callback is a block pointer instead of a function pointer.

The qsort_b function would have been handy for a sorting task I was implementing on the iPhone, but of course it wasn’t available. I thought for a while about I might go about implementing a replacement without reimplementing the whole qsort function. In the end I was able to, but only through the use of some undefined behavior and an unexpectedly useful qsort_r variant.

The qsort_r function takes a void* thunk that is passed unmodified as context to each invocation of the compar function.

void qsort_r(void *base, size_t nel, size_t width, void *thunk, int (*compar)(void *, const void *, const void *));

My implementation relies on passing the block pointer in the thunk parameter, which is undefined behavior (passing a function pointer through a void type and back is undefined, so I assume the same is true of a block pointer), but it works.

typedef int (^ds_compare_block_t)(const void*, const void*);

int ds_qsort_block_adapter(void* cmp, const void* a, const void* b) 
{
    return ((ds_compare_block_t)cmp)(a, b); // this is undefined behavior
}

void ds_qsort_b(void* base, size_t nel, size_t width, ds_compare_block_t cmp)
{
    qsort_r(base, nel, width, cmp, ds_qsort_block_adapter);
}

Of course this is a very specific solution to the case of qsort (mergesort and heapsort would be out of luck). A more general solution to the problem of passing a block (via some adapter) to existing C library functions would be welcome, but I’m not sure it’s even possible.