Arbitrary Function Arrays

R

Randy Yates

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?
 
E

Eric Sosman

Randy said:
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_descriptor*'. 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.
 
D

Daniel Haude

On 11 Mar 2005 08:14:44 -0500,
in Msg. said:
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?

To the actual question, see Eric's exhaustive posting. I'd just like to
ask: If it was possible to construct an array of pointers to functions
with different signatures, what good would it do you? I'm just curious
about what you're trying to accomplish here.

--Daniel
 
T

Tommy Reynolds

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?

C doesn't let you overload function definitions. Maybe something
like this is what you're looking for:

typedef struct arbfunc_s {
union {
int (*i)(.....);
char * (*c)(.....);
} u;
int kind;
} arbfunc_t;

arbfunct_t actions[ 100 ] = {
{ intfunc, IS_INT },
{ anotherIntFunc, IS_INT },
{ mychar, IS_CHAR }
{ 0 }
};

....
arbfunc_t * ap = actions;
....
for( ap = actions; ap->kind > 0; ++ap ) {
switch( ap->kind ) {
case IS_INT: results = (ap->u.i)(....); break;
case IS_CHAR: results = (ap->u.c)(...); break;
}
}

depending on what you're doing, this may work.

Cheers
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top