3

Je voudrais savoir comment j'irais passer n'importe quelle fonction à une fonction, comme dans un pointeur de fonction générique qui peut prendre n'importe quelle fonction, Le but de ceci est de faire un destructeur système, donc essentiellement le stockage de la fonction et de l'appeler avec ses arguments également stockés plus tard la ligne,C: Passer n'importe quelle fonction à une fonction

Quelque chose comme:

Defer(SDL_DestroyWindow, Window); 

je déjà traité les arguments, mais je ne sais pas comment gérer la partie de pointeur de fonction de ceci, merci!

Edit: J'ajouté plus d'info ...

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 */ 
    } 
} 

Je n'ai pas les fonctions réelles de Defer, mais je l'ai fait copier tous les arguments dans la pile et peut les pop avec succès, je ne savoir comment implémenter la fonction variadique appeler si

Edit2: Après avoir reçu une entrée: Je pense que ce serait plus réalisable: Defer (SDL_DestroyWindow, « SDL_Window * », fenêtre); Je suis brainstorming comment cela serait possible, mais j'apprécierait une entrée

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); 
    } 
} 

C'est ce que je suis venu avec, mais je me demande comment je peux conver que char * en tapez ...

+0

Vous pouvez faire quelque chose avec des astuces macro-variées, bien que je sois rouillé dessus;) –

+2

Tout pointeur de fonction d'un type peut être converti en un pointeur de fonction d'un autre type. Donc utiliser 'foo (int (* f)()) {...}' est suffisant pour passer un pointeur de fonction (la _value_). L'astuce est de savoir comment passer le _type_. Code utilise un 'union' et une valeur énumérée pour une liste finie de types - mais _any_ type? -> recommande de réduire l'objectif. – chux

+0

@chux - Le problème est alors de savoir comment passer un nombre variable d'arguments à un pointeur de fonction (non-variadique). –

Répondre

0

Comme je l'ai dit dans le commentaire un gros problème est que lors de la déclaration d'une fonction variadique les paramètres non déclarés sont soumis à la default argument promotions. Cela signifie que vous pouvez trouver les arguments passés différents de ceux prévus par la fonction, ce qui conduira éventuellement à des exceptions. Ce que vous voulez faire est réalisable, mais vraiment très complexe.

Une solution, mais limitée, car il faut beaucoup de codage, pourrait être:

#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

Vous devriez jeter un oeil à Fake Function Framework (fff) sur GitHub. Ils l'ont fait en utilisant des macros pour la mise en cache des fonctions fictives. MIT sous licence. Cependant, tout comme @Frankie_C dit, cela nécessite beaucoup de code. Le fichier d'en-tête qui définit toutes les macros est environ 6K LOC. Et les fonctions sont toujours limitées à 20 arguments.