C: Pass any function to a function

I would like to know how I would like to pass any function to a function, as in a generic function pointer that can accept any function at all. The purpose of this is to create a destructor system, so basically saving the function and calling it with arguments, which are then saved later.

Something like:

Defer(SDL_DestroyWindow, Window); 

      

I've already handled the arguments, but I don't know how to manipulate the function pointer part of this, thanks!

Edit: I've added some additional information ...

typedef struct {
  void** args;
} IM_Defer_Resource;
/* Defer & Whatnot */

IM_Stack* IM_Defer_Stack;

void IM_Defer_Init() {
  IM_Defer_Stack = IM_Stack_Init();
}


void IM_Defer(/* What to put here? */) {

}

void IM_Defer_All() {
  while(IM_Defer_Stack->size) {
    IM_Defer_Resource* resource = IM_Stack_Pop(IM_Defer_Stack);
    if(!resource) continue;
    /* What to do */
  }
}

      

I don't have actual defer functions, but I copied each argument onto the stack and was able to successfully push them, I don't know how to implement a variational function calling, though

Edit2: After getting some input: I think it would be more doable: Defer (SDL_DestroyWindow, "SDL_Window *", window); I think it is possible, but I would appreciate some data input

Edit3:

/* Defer & Whatnot */
typedef struct {
  char** types;
  void** args;
  int count;
} IM_Defer_Resource;


IM_Stack* IM_Defer_Stack;

void IM_Defer_Init() {
  IM_Defer_Stack = IM_Stack_Init(IM_Get_Stack_Type(IM_Defer_Resource));
}

void IM_Defer_Internal(void* var, int n, ...) {
  char* type;
  void* arg;

  va_list args;
  va_start(args, n);

  IM_Defer_Resource resource;
  int count = n / 2;
  resource->types = calloc(count, sizeof(char*));
  resource->args = calloc(count, sizeof(void*));
  resource->count = count;

  for(count > 0; n -= 1) {
    type = va_arg(args, char*);
    resource->types[count-1] = type;
    arg = va_arg(args, void*);
    resource->args[count-1] = arg;
  }

  IM_Stack_Push(IM_Defer_Stack, &resource);
}

void IM_Defer_All() {
  while(IM_Defer_Stack->size) {
    IM_Defer_Resource* resource = IM_Stack_Pop(IM_Defer_Stack);
    if(!resource) continue;
    /* I have a char* and a void* to the resource, Now what? */
    free(resource->types);
    free(resource->args);
  }
}

      

This is what I came up with, but I'm wondering how I can convert this char * to a type ...

+3


source to share


2 answers


As I said in the comment, the big problem is that when you declare a variational function, the undeclared parameters are obeyed default argument promotions

. This means that you may find passed arguments different from those intended by this function, which will eventually lead to exceptions. What you want to do is doable, but really difficult.

One solution, but limited because it requires a lot of coding, could be:



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

typedef enum { fn1, fn2, fn3, /*....*/} e_fn;

void multi_fun(e_fn fn, ...)
{
    va_list ap;
    int j;

    va_start(ap, fn); /* Requires the last fixed parameter (to get the address) */

    switch(fn)
    {
        case fn1:
        {
            //suppose prototype for fn1 to be void fn1_fn(int, float, struct  mystruct *);
            int   this_int   = va_arg(ap, int);
            float this_float = va_arg(ap, float);
            struct  mystruct *this_struct = va_arg(ap, struct  mystruct *);
            fn1_fn(this_int, this_float, this_struct);
            break;
        }

        case fn2:
        {
            ...
        }
    }
    va_end(ap);
}

      

0


source


You should take a look at Fake Function Framework (fff) on GitHub. They did it using macros to cache mock functions. MIT license. However, like @Frankie_C, this requires a lot of code. The header file defining all macros is about 6K LOC. And functions are still limited to 20 arguments.



0


source







All Articles