The question pretty much says it all.
I'm not sure how to do this and haven't come anywhere near anything that works.
Here's some example functions:
add(int x, int y) {
return x+y;
}
and,
mean(int x1, int y1, int x2, int y2) {
return (x1 + y1 + x2 + y2) / 4;
}
So far I've tried using typedef with both, but I can't figure how to make something point to one of either type:
typedef int (*mathfunc2)(int x, int y);
typedef int (*mathfunc4)(int x1, int y1, int x2, int y2);
????? func_table[2] = {add, mean};
You need to pick a function pointer type to use as a "generic function pointer", use that type to define your array, and use explicit casts. Casting one function pointer type to another and then back again is guaranteed to preserve the value.
In other words:
typedef int (*generic_fp)(void);
generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean };
Then to call add
, you need to cast it back to the right type:
result = ((mathfunc2)func_table[0])(x, y);
You can define some macros if you find it more palatable:
#define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2)
#define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4)
result = FUNC_2(func_table[0], x, y);
You could use the Facade Pattern like this:
int add(int x, int y);
int mean(int x1, int y1, int x2, int y2);
typedef int (*operation_fp)(int argc, int* argv);
int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); }
int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); }
operation_fp func_table[2] = { add_wrapper, mean_wrapper };
Although the code is ugly, it does the job. You should add some validation logic in wrappers.
int (*func[])() = { add, mean };
These two function types are incompatible. Strictly speaking, they could be implemented using completely different argument passing. An implementation might choose, for example, that all functions with up to 3 parameters receive them via registers, and all other functions receive them via the stack.
What you can do though is to define both functions with varargs parameters to make them follow the same parameter passing scheme.
How did you intend to call these functions anyway, not knowing how many parameters they expect?