Randy Yates wrote:
Hi,
We know we can build arrays of variables of the same type and arrays
of functions of the same "type" (i.e., same return value and same
parameters), but is there a way to automate the calling of a sequence
of functions with arbitrary return types and/or parameters?
Functions cannot be array elements: they are not data
objects, and they do not have size. You are probably thinking
of an array of pointers to functions; pointers are data objects,
have size, and can be elements in an array.
Next, all the elements in an array of function pointers
must have the same type. This is the same as for any other
array: you can't have an array whose [0] element is an `int',
whose [1] element is a `double', and whose [2] element is a
`const struct muggle_descript or*'. The pointers may, however,
have been converted from disparate types to a common type by
casting -- of course, they've got to be converted back to match
the actual called function at the point of the call.
However, the function call construct in C is "static" in
the sense that the type of the return value and the number and
types of the arguments are fixed at compile time. Even for a
variadic function, which can be called with differing argument
lists at different points in the program, the circumstances of
any particular call in the source are unchangeable. When you
write `foo(x,y)' the call passes exactly two arguments of
exactly the same type, every time you execute it. There's no
way to get rid of an argument, add an argument, or change the
type of an argument other than by editing and recompiling.
I've encountered two approaches to working around this
inflexibility. One is to enumerate all the function types
of interest, and to use a big `switch' or something of the
kind to choose between the appropriate calls:
fptr = ...;
switch (ftype) {
case INT_VOID:
intres = ((int(*)(void)) f)();
break;
case DBL_INT:
dblres = ((double(*)(int ))f)(42);
break;
...
This becomes messy unless the number of different function
signatures is quite small.
A second approach is to use "wrapper" functions. You use
an array of `void*' or an array of unions or some such to hold
the actual arguments -- you can build the array at run-time --
and pass it to the wrapper. The wrapper plucks the appropriate
arguments from the array, passes them to the target function,
and returns the result. As a variation, you can use one wrapper
for each different target function signature, passing a pointer
to the target function along with the array of "anonymous"
arguments.
--
Eric Sosman
es*****@acm-dot-org.invalid