Pointeur de fonction

Version imprimable

Voir 40 message(s) de cette discussion en une page
Page 2 sur 2 PremièrePremière 12


Ca permet de fabriquer des bibliothèques qui peuvent PREVOIR d'avoir des actions SANS les connaître (comme signal par exemple).
  • 21/06/2007, 00h14
    souviron34
    Citation:

    Envoyé par acx01b
    salut


    void Fonction ( void MaFonction, void *Data )
    {
    MaFonction ( Data );
    }

    ?????????
    c'est pas vraiment du C !


    Ah oui ? et pourquoi pas ?
  • 21/06/2007, 00h19
    souviron34
    Bon je vais mettre un code propre (avec les void je suis pas certain que les adresses et les stockages marchent totalement) :

    Code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
     
     
    #include <stdio.h>
     
    typedef struct {
       int a ;
       int b ;
       int result ;
    } MonData ;
     
    typedef int MAPROC (void *data);
     
    typedef struct {
        int     Type ;
        MAPROC *Adr ;
        void   *Data ;
    } Fct ;
     
     
    #define ADD  1
     
    #ifndef SUCCESS
    #define SUCCESS 0
    #define ERROR 1
    #endif
     
     
    static Fct *Fcts=NULL ;
    static int    NFcts=0 ;
     
    MAPROC add (void *Data) 
    {
       MonData *mdata = (MonData *)Data ;
     
        mdata->result = mdata->a + mdata->b;
     
       return SUCCESS ;
    }
     
     
    int StockeFonction ( int Type, MAPROC *MaFct, void *Data )
    {
       Fct tmp =NULL ;
     
        if ( NFcts == 0 )
          {
              Fcts = calloc ( 1, sizeof(Fct) );
              if ( Fcts == NULL )
                 return ERROR ;
          }
        else
          {
             tmp = realloc ( Fcts, ((NFcts+1)*sizeof(Fct)) );
             if ( tmp == NULL )
               return ERROR ;
             Fcts = tmp ;
          }
     
        Fcts[NFcts].Adr = MaFct ;
        Fcts[NFcts].Type = Type ;
        Fcts[NFcts].Data = Data ;
        NFcts = NFcts + 1 ;
     
        return SUCCESS ;
    }
     
     
    int AppelleFonction ( int Type )
    {
       int i, j ;
     
       for ( i = 0 ; i < NFcts ; i++ )
          if ( Fcts[i].Type == Type )
             {
                j = Fcts[i].Adr ( Fct[i].Data );
                return j ;
              }
    }
     
    int main(void) {
        MonData Data ;
     
        Data.a = 5;
        Data.b = 10;
        Data.result = 0;
     
        if ( StockeFonction ( ADD, (MAPROC *)&add, (void *)&Data ) )
          {
             fprintf ( stderr, "\nUne erreur s'est produite...\n");
             return EXIT_FAILURE ;
          }
     
        AppelleFonction ( ADD );
     
        printf("resultat : %d\n",Data.result);
     
        return EXIT_SUCCESS ;
    }

  • 21/06/2007, 00h21
    AuraHxC
    Merci pour toutes ces précisions ;)
    Et je ne doutais pas du tout que c'était du C ce que tu avais mis :D
    J'ai même capté à la première lecture ce que tu faisais ;)
  • 21/06/2007, 01h59
    Emmanuel Delahaye
    Citation:

    Envoyé par souviron34
    Bon je vais mettre un code propre (avec les void je suis pas certain que les adresses et les stockages marchent totalement) :
    <...>

    Ahem... Tu n'as pas compilé le code posté, çaÿ mal.

    Code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    Compilateur: Default compiler
    Building Makefile: "C:\dev\forums\Makefile.win"
    Exécution de  make...
    make.exe -f "C:\dev\forums\Makefile.win" all
    gcc.exe -c main.c -o main.o -I"C:/Dev-Cpp/include"  -I"/clib"    -Wextra -Wall -O2
     
    main.c:30: error: `add' declared as function returning a function
    main.c: In function `StockeFonction':
    main.c:41: error: invalid initializer
    main.c:45: warning: implicit declaration of function `calloc'
     
    main.c:51: warning: implicit declaration of function `realloc'
     
    main.c:51: error: incompatible types in assignment
    main.c:52: error: invalid operands to binary ==
    main.c:54: error: incompatible types in assignment
    main.c: In function `AppelleFonction':
    main.c:73: error: syntax error before "Fct"
    main.c: In function `main':
    main.c:88: error: `EXIT_FAILURE' undeclared (first use in this function)
    main.c:88: error: (Each undeclared identifier is reported only once
    main.c:88: error: for each function it appears in.)
    main.c:95: error: `EXIT_SUCCESS' undeclared (first use in this function)
     
    make.exe: *** [main.o] Error 1
     
    Exécution terminée

    En dehors des erreurs signalées, il y des casts et des & inutiles. Ceci compile :
    Code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct {
       int a ;
       int b ;
       int result ;
    } MonData ;
     
    typedef int MAPROC (void *data);
     
    typedef struct {
        int     Type ;
        MAPROC *Adr ;
        void   *Data ;
    } Fct ;
     
     
    #define ADD  1
     
    #ifndef SUCCESS
    #define SUCCESS 0
    #define ERROR 1
    #endif
     
    static Fct *Fcts=NULL ;
    static int    NFcts=0 ;
     
    int add (void *Data)
    {
       MonData *mdata = Data ;
     
        mdata->result = mdata->a + mdata->b;
     
       return SUCCESS ;
    }
     
     
    int StockeFonction ( int Type, MAPROC *MaFct, void *Data )
    {
       Fct *tmp =NULL ;
     
        if ( NFcts == 0 )
          {
              Fcts = calloc ( 1, sizeof(Fct) );
              if ( Fcts == NULL )
                 return ERROR ;
          }
        else
          {
             tmp = realloc ( Fcts, ((NFcts+1)*sizeof(Fct)) );
             if ( tmp == NULL )
               return ERROR ;
             Fcts = tmp ;
          }
     
        Fcts[NFcts].Adr = MaFct ;
        Fcts[NFcts].Type = Type ;
        Fcts[NFcts].Data = Data ;
        NFcts = NFcts + 1 ;
     
        return SUCCESS ;
    }
     
    int AppelleFonction ( int Type )
    {
       int i, j=-1 ;
     
       for ( i = 0 ; i < NFcts ; i++ )
          if ( Fcts[i].Type == Type )
             {
                j = Fcts[i].Adr ( Fcts[i].Data );
             }
       return j ;
    }
     
    int main(void) {
        MonData Data ;
     
        Data.a = 5;
        Data.b = 10;
        Data.result = 0;
     
        if ( StockeFonction ( ADD, add, &Data ) )
          {
             fprintf ( stderr, "\nUne erreur s'est produite...\n");
             return EXIT_FAILURE ;
          }
     
        AppelleFonction ( ADD );
     
        printf("resultat : %d\n",Data.result);
     
        return EXIT_SUCCESS ;
    }

    Attention, à vue de nez, ce qui a été alloué n'a pas été libéré...
  • 21/06/2007, 15h20
    souviron34
    Citation:

    Envoyé par Emmanuel Delahaye
    Ahem... Tu n'as pas compilé le code posté, çaÿ mal.

    OUI c'est vrai....

    :oops: :oops:

    J'ai juste voulu donner un exemple en copiant des morceaux de code que j'avais, pas faire un truc compilable... Désolé..

    Citation:

    Envoyé par Emmanuel Delahaye
    Attention, à vue de nez, ce qui a été alloué n'a pas été libéré...

    Même réponse .. Même faute.. Encore une fois désolé .. :oops:
  • 22/06/2007, 16h42
    AuraHxC
    Tiens j'ai remarqué qu'il y avait un commentaire dans la fonction list_destroy qui utilise un pointeur de fonction :
    Code:

    1
    2
    3
     
    /*appel d'une fonction utilisateur pour libérer */
    /*les données allouées dynamiquement         */

    Comme on a parlé dans ce thread de fonction utilisateur, ben je viens de tilter sur le fait que je vois pas exactement ce que c'est... Quand il met ça en commentaire, est ce que ca veut dire qu'il faut que je fasse une fonction pour supprimer ma liste ?

    Je remets du code pour une meilleur compréhension :

    Code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    typedef struct ListElmt_ {
        void *donnee;
        struct ListElmt_ *suivant;
    } ListElmt;
     
    typedef struct List_ {
        int taille;
        int (*corresp)(const void *val1,const void *val2);
        void (*detruire)(void *donnee);
        ListElmt *tete;
        ListElmt *queue;
    } List;

    Code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    void list_init(List *liste, void (*detruire)(void *donnee)) {
        liste->taille   = 0;
        liste->detruire = detruire;
        liste->tete     = NULL;
        liste->queue    = NULL;
     
        return;
    }
     
    void list_destroy(List *liste) {
        void *donnee;
     
        while (list_size(liste) > 0) {
     
             if (list_rem_next(liste, NULL, (void **)&donnee) == 0 && liste->detruire !=  NULL) {
     
          /*****************************************************
          *                                                    *
          *  Appel d'une fonction utilisateur pour libérer     *
          *  les données allouées dynamiquement.               *
          *                                                    *
          *****************************************************/
     
                    liste->detruire(donnee);
       }
    }
     
        memset(liste, 0, sizeof(List));
     
        return;
    }

    J'ai essayé de faire de mon mieux pour réindenter le code, j'espère que ça donne pas trop mal.

    Merci d'avance pour vos réponse, ça va sûrement bien m'aider.
  • 22/06/2007, 16h56
    souviron34
    ben oui...

    sa structure est générique. Il gère une liste quelconque...

    Dans cette liste, on a des TAD (ou des objets opaques si tu préfères).

    Donc dans ces objets tu peux avoir des choses allouées.

    Donc avant de détruire l'objet, il faut éventuellement détruire ce qui a été alloué.

    Comme la structure est générique, elle n'a aucun moyen de savoir si des choses ont été allouées ou non. En conséquence c'est au programme appellant de définir la(les) routine(s) de destruction interne.
  • 22/06/2007, 17h05
    AuraHxC
    Donc il faut que je définisse une fonction qui permette de détruire les données de ma liste... Je vais y aller par étape parce que ce genre d'implémentation j'en ai jamais vu donc j'ai un peu de mal à capter correctement.
  • Voir 40 message(s) de cette discussion en une page
    Page 2 sur 2 PremièrePremière 12