Felix said:
in a given library I register callback functions with this function:
bool set_callback(int index, int (*callback_function)(long));
I need the callback function to also pass the index which is, however,
not (re-)passed by the callback function.
Why do you _need_ the index?
Normally, I would just register callback functions for each
index I need if the amount of callback functions was known at
design time... But it isn't.
Could someone help me find the right approach to solve that problem?
The right approach is make your callback functions independant of
the index, or to persuade the library writers to redesign their
callback interface.
A kludge though is something like the code below. You make your
callback functions take the int parameter (A, B and C below),
and put a wrapper around the the set_callback function...
#include <stdio.h>
#include <stdlib.h>
typedef int wrapper_f(long);
typedef int callback_f(int, long);
#define countof(x) (sizeof(x) / sizeof *(x))
#define blank
#define semicolon ;
#define comma ,
/* specify the indexes to wrap with this macro */
#define the_indexes(M,_) \
M( 1) _ \
M( 2) _ \
M( 7) _ \
M(12) _ \
M(42)
struct wt_element_t
{
const int index;
wrapper_f * const wrapper;
callback_f *callback;
};
struct wt_element_t wrapper_table[];
#define as_enums(I) wrapper_ ## I ## _e
#define as_initialisors(I) { I, wrapper_ ## I, 0 }
#define as_function_declarations(I) \
int wrapper_ ## I (long)
#define as_function_definitions(I) \
int wrapper_ ## I (long n) \
{ \
return wrapper_table[wrapper_ ## I ## _e]. \
callback(I, n); \
}
enum my_wrapper_enums { the_indexes(as_enums, comma) };
the_indexes(as_function_declarations, semicolon);
/* put these in a single source file */
the_indexes(as_function_definitions, blank)
struct wt_element_t wrapper_table[] =
{ the_indexes(as_initialisors, comma) };
int set_callback_wrapper(int index, callback_f *callback)
{
size_t i;
for (i = 0; i < countof(wrapper_table); i++)
if (wrapper_table
.index == index)
{
wrapper_table.callback = callback;
/* install the wrapper callback function */
/* set_callback(index, wrapper_table.wrapper); */
return 1;
}
return 0;
}
/* sample usage */
/* your callback functions */
int A(int i, long n) { return printf("A(%2d, %3ld)\n", i, n); }
int B(int i, long n) { return printf("B(%2d, %3ld)\n", i, n); }
int C(int i, long n) { return printf("C(%2d, %3ld)\n", i, n); }
int main(void)
{
long n;
/* install callbacks */
set_callback_wrapper( 1, A);
set_callback_wrapper( 2, B);
set_callback_wrapper(12, C);
set_callback_wrapper(42, A);
/* simulate 20 pseudo random callbacks */
for (n = 1; n <= 20; n++)
{
size_t i = rand() % countof(wrapper_table);
while (wrapper_table.callback == 0)
i = (i + 1) % countof(wrapper_table);
wrapper_table.wrapper(n);
}
return 0;
}