1

I need to make a "function caller" function: it receives a generic function pointer (void *) and a variable number of arguments as arguments and it's got to call this function, passing the arguments, and return a generic pointer to the returning value. However, this entry-function pointer may point to any kind of function (with any returning type), even to functions with a constant number of arguments. It would be something like:

void * function_caller(void * function_pointer, ...) {
  void * returning_value;

  // Call the function and get the returning value

  return returning_value;   // this returning value will be properly casted outside
}

This way, the following code would work:

int function1(int a, char b) {
  // ...
}

void function2(float c) {
  // ...
}

float function3() {
  // ...
}

int main() {
  int v1;
  float v3;

  v1 = *(int *) function_caller((void *) &function1, 10, 'a');  // Which would be equivalent to v1 = function1(10, 'a');
  function_caller((void *) &function2, 3.0);    // Which would be equivalent to function2(3.0);
  v3 = *(float *) function_caller((void *) &function3); // Which would be equivalent to v3 = function3();

  return 0;
}

I know I'll have to use a va_list, but I don't know how to call the function by a pointer passing the arguments.

So, guys, any idea?

1 Answer 1

5

The bad news is, this is not possible in C, even in unportable C. (GCC has extensions which sound like they do this job, but they do not work in the general case.) It is necessary to write assembly-language shims.

The good news is, other people have already written the shims for you: have a look at libffi. (Manual here. Do not use the "closure" API if you can possibly avoid it.)

Sign up to request clarification or add additional context in comments.

3 Comments

Aside from this, what the questioner wants isn't necessarily possible for a second reason, which is that function_caller takes varags. So for example the vararg 3.0 is passed as a double (and would be even if it was 3.0f), and the type of the first argument has stripped the parameter types of function2. Therefore even once you play your assembler tricks, the only way you could possibly determine that the parameter should be passed as a float rather than a double is by examining function2 itself to see whether it expects a float or a double. Which seems a bit implausible.
Libffi sounds quite interesting :-)
@SteveJessop Your observation is quite justifiable, but in my application (as I haven't explained), functions are identified by their pointers and by encoding-strings which store returning and argument types. So, there is a arguments checking before the function calling. The example above is only an approximation of what I need to do, so things aren't going to work exactly that way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.