Neat. But how do you make this modular and still safe? When the code invoking qsort() does not know about how many callbacks there are, can you still deal with it?
struct danger {
sort_fn sorter;
char data[16];
};
danger->sorter(danger); /* what if it's a bad pointer? */
You replace that with this. int add_sort_fn(sort_fn sorter) {
sort_fns[num_sorts++] = sorter;
return num_sorts;
}
struct lessdanger {
int sortidx;
char data[16];
};
danger->sortidx = add_sort_fn(sorter);
/* could clean this up a bit more */
sort_fns[danger->sortidx % num_sorts](danger);
There's still the possibility of calling the wrong function, but only one from a finite set of possibilities. There's no direct control over the pointer value.You can make the sort_fns array resizeable, but in practice there's usually only so many targets.
You would need a linker script to collect the callbacks into a section and provide a symbol for the end, and define variables something like
int (my_sort_callback_ptr)(void , void *) __attribute__((section, "sort_callbacks"))=my_sort_comparator;
You would, of course, use a macro for that.