2

I'm not sure I have the best title for this question, feel free to improve.

If I have

typedef void (*VoidFunction)(void);

And then a family of functions that fit this type, I could write a sort of "transaction" wrapper function that looked something like:

void doTransaction(VoidFunction function)
{
    doSomePreambleWork();
    function();
    doSomePostambleWork();
}

If I had a family of functions that took single int arguments, I could wash-rinse-repeat:

typedef void (*VoidOneIntFunction)(int a);
void doTransactionOneInt(VoidFunctionOneInt function, int a)
{
    doSomePreambleWork();
    function(a);
    doSomePostambleWork();
}

Leaving the issue of return types (iow, assuming a void return type), is it possible to genericize this pattern, so that I only have to do write one wrapper function, something like:

// ????? I'm not sure how i'd type the passed function
void doTransactionGeneric(void * function, ...)
{
    doSomePreambleWork();
    function(); // ????? and i don't know how i'd go about calling it...
    doSomePostambleWork();
}
3
  • Take a look at the <stdarg.h> header. The solution is to use a variable argument list. Commented Apr 24, 2013 at 17:28
  • @Will I don't think that's what OP is asking for. Commented Apr 24, 2013 at 17:29
  • I was hoping for something more "meta" than these answers. Maybe it's just not possible with C. I thought I could mess with the stack somehow, to invoke the first argument of the call stack (known to be a function) with the remainder of the call stack magically somehow. :( Commented Apr 25, 2013 at 6:40

3 Answers 3

2

If you want to use the ... syntax, known as variadic parameters, then you use va_list to access the parameter list, eg:

#include <stdarg.h>

typedef void (*VoidArgsFunction)(va_list args);

void doTransactionGeneric(VoidArgsFunction function, ...)
{
    doSomePreambleWork();

    va_list args;
    va_start(args, function);
    function(args);
    va_end(args);

    doSomePostambleWork();
}

Inside of the called function, it can use va_arg() to access the individual parameter values from the va_list as needed, eg:

#include <stdarg.h>

void someFunction(va_list args)
{
    int param1 = va_arg(args, int);
    char *param2 = va_arg(args, char*);
    ...
}

doTransactionGeneric(&somefunction, 12345, "Hello World");
Sign up to request clarification or add additional context in comments.

Comments

0

I'm not sure how i'd type the passed function

Just like you would declare a function pointer anywhere else:

void doTransactionGeneric(void (*function)(void), ...)

and I don't know how I'd go about calling it...

Just like you already did:

function();

1 Comment

If you declare function like that, you would not be able to pass variadic parameters to doTransactionGeneric() itself and pass them along to the specified function.
0

Here is a suggestion.

Assuming you have several functions (like in your question):

typedef void (*VoidFunction)(void);
typedef void (*VoidFunctionOneInt)(int);
// we can add more

Let's define type enumeration (we don't have to use the enumeration, but this is more illustrative):

typedef enum
{
   e_fn_void,     // void return, no args
   e_fn_void_int, // void return, one int
                  // we can add more...
} void_function_kind_t;

Then, lets say, we have some generic processor. We need to supply type of the function, function pointer, and arguments:

void some_generic_function(void_function_kind_t kind, void *fn, ...)
{
   va_list args;
   va_start(args, fn);

   // here - make a call
   switch (kind)
   {
   case e_fn_void:
        // no arguments
        ((VoidFunction)fn)();
        break;
   case e_fn_void_int:
        {
           int arg0 = va_arg(args,int);
           ((VoidFunctionOneInt)fn)(arg0);
        }
        break;
   default: // error - unsupported function type
        break;
   }

   va_end(args);
}

Comments

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.