steve landiss
steve landiss

Reputation: 1903

How do I pass a function AND a variable list of arguments to another function in C?

I want to pass an arbitrary function and it's arguments to another function in C.

For example like the code below (which obviously does not work)

#include <stdio.h>

void doit(int (*f)(...), char *fname, ...)
{
    va_list argptr;
    va_start(argptr, fname);
    f(argptr)
    va_end(argptr);
}   

int func1(char *a, int b)
{
    fprintf(stderr, "func1 %s %d\n", a, b);
}   

int func2(char *a, int b, int c)
{
    fprintf(stderr, "func2 %s %d %d\n", a, b, c);
}

int main(int argc, char **argv)
{

    doit(func1, "func1", "blah", 10);

    return 0;
}   

Upvotes: 3

Views: 492

Answers (2)

Bruce David Wilner
Bruce David Wilner

Reputation: 469

First: don't mess with va_args if you have no idea how arguments are passed or how activation records work.

Your best bet is to declare doit() with excessively many args:

void doit( void ( *p_func )(), int arg1, int arg2, int arg3, int arg4, int arg5 );

and just call ( *p_func )() with all those arguments. If the function being called doesn't reach for more than it needs, there won't be any trouble. Even if it does, it will just pull garbage values off the stack.

Upvotes: 0

WhozCraig
WhozCraig

Reputation: 66194

You need va_list forwarders to your functions if you want to have them participate in such a scheme. Something like:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

void doit(int (*f)(va_list va), char *fname, ...)
{
    va_list argptr;
    va_start(argptr, fname);
    f(argptr);
    va_end(argptr);
}

int func1(const char *a, int b)
{
    fprintf(stderr, "func1 %s %d\n", a, b);
    return 0;
}

int func1_va(va_list va)
{
    const char * a = va_arg(va, const char*);
    int b = va_arg(va, int);
    return func1(a,b);
}

int func2(const char *a, int b, int c)
{
    fprintf(stderr, "func2 %s %d %d\n", a, b, c);
    return 0;
}

int func2_va(va_list va)
{
    const char *a = va_arg(va, const char*);
    int b = va_arg(va, int);
    int c = va_arg(va, int);
    return func2(a,b,c);
}

int main(int argc, char **argv)
{

    doit(func1_va, "func1", "blah", 10);
    doit(func2_va, "func2", "blahblah", 100, 200);

    return 0;
}

Output

func1 blah 10
func2 blahblah 100 200

Upvotes: 5

Related Questions