IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Déclaration de pointeur de fonction et structure


Sujet :

Delphi

  1. #21
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    En plus une procedure of object c'est deux 'pointeurs cachés' : celui de la procedure + celui de l'objet .

  2. #22
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    tu raconte n'importe quoi
    je n'ai fait appel qu'à des methodes published donc verifier lors de la conpilation
    mes appelles ne se font que par le MethodAddress
    en fait elle ne cherche que des methode existante
    le fait que tu passe @maprocedure c'est exactement la meme chose
    la seul difference c'est que je le fait dynamiquement lors de l'utilisation


    @+ Phil

  3. #23
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 577
    Points : 25 225
    Points
    25 225
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    TShaiMappingStruct = record
        FSetProc : TShaiMappingSetter;
        FShaiMappingStruct : TShaiMappingData;
        procedure SetProc (const Source, Destination: TDataSet );inline;
      end;
     
    { TShaiMappingStruct }
     
    procedure TShaiMappingStruct.SetProc(const Source, Destination: TDataSet);
    begin
        FSetProc(FShaiMappingStruct,Source, Destination);
    end;
    gb_68, tu n'aurais pas confondu Record et Class, ceci est impossible bien sur ...

    une méthode d'objet ben c'est TMethod ... je vois pas pourquoi, vous n'êtes pas d'accord tous les deux, vous racontez la même chose non d'un point de vue différent ?

    sinon anapurna, je n'ai plus de @ pour la méthode SetProc et la recherche par nom publié ne garanti pas la compilation de la table d'assoc, et le code objet est plus long impliquant allocation et libération contre un tableau constant qui finallement est dans le principe du RTTI qui ne sont que des constantes ...

    voici le code final sans pointeur, sans @, et safe-compilation merci à vous deux

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    // Mapping
    type
      TSourceDestinationMapping = (...censored ...);
      TSourceMappingData = record
        SourceName : string;      // Champ dans la Table Source
        DestinationName: string;  // Champ dans la Table Destination
        SourceValue: string;      // Champ qui sera comparé au Champ Source
        DestinationValue: string; // Champ qui sera affecté au Champ Destination
        RelationName: string;     // Champ dans la Table Source qui sert pour un Test
      end;
      TSourceMappingSetter = procedure(const Item: TSourceMappingData; const Source, Destination: TDataSet);
      TSourceMappingWrapper = record
        SetProc: TSourceMappingSetter; // Procédure d'Affectation du Champ Destination
        Data: TSourceMappingData;
      end;
     
    // Test si le Champ Destination est Vide, car on ne doit pas l'écraser
    function IsEmptyDest(DestinationField: TField): Boolean;
    begin
       Result := DestinationField.IsNull or (Trim(DestinationField.AsString) = '');
    end;
     
    // Affectation Simple
    procedure StandardSetter(const Item: TSourceMappingData; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField: TField;
    begin
      SourceField := Source.FindField(Item.SourceName);
      DestinationField := Destination.FindField(Item.DestinationName);
      if Assigned(SourceField) and Assigned(DestinationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
        DestinationField.AsVariant := SourceField.AsVariant;
    end;
     
    // Affectation d'une Constante en fonction de la Valeur de la Source
    procedure TestConstSetter(const Item: TSourceMappingData; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField: TField;
    begin
      SourceField := Source.FindField(Item.SourceName);
      DestinationField := Destination.FindField(Item.DestinationName);
      if Assigned(SourceField) and Assigned(DestinationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
      begin
        if SourceField.AsString = Item.SourceValue then
          DestinationField.AsVariant := Item.DestinationValue;
      end;
    end;
     
    // Affectation en fonction de la Valeur d'un autre Champ de la Source
    procedure RelativeSetter(const Item: TSourceMappingData; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField, RelationField: TField;
    begin
      SourceField := Source.FindField(Item.SourceName);
      DestinationField := Destination.FindField(Item.DestinationName);
      RelationField := Source.FindField(Item.RelationName);
      if Assigned(SourceField) and Assigned(DestinationField) and Assigned(RelationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
      begin
        if RelationField.AsString = Item.SourceValue then
          DestinationField.AsVariant := SourceField.AsVariant;
      end;
    end;
     
    // Affectation Simple mais Retire le Point de l'ADICAP ou CIM10
    procedure WithoutPointSetter(const Item: TSourceMappingData; const Source, Destination: TDataSet);
    var
      SourceField, DestinationField: TField;
    begin
      SourceField := Source.FindField(Item.SourceName);
      DestinationField := Destination.FindField(Item.DestinationName);
      if Assigned(SourceField) and Assigned(DestinationField) and not SourceField.IsNull and IsEmptyDest(DestinationField) then
        DestinationField.AsString := AnsiReplaceText(SourceField.AsVariant, '.', '');
    end;
     
    const
      Source_MAPPING : array[TSourceDestinationMapping] of TSourceMappingWrapper =
      (
        (SetProc: WithoutPointSetter; Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: WithoutPointSetter; Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: WithoutPointSetter; Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: WithoutPointSetter; Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )), // Valeur Plus Significative que censored
        (SetProc: RelativeSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; SourceValue: 'O'; RelationName: 'censored')),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: TestConstSetter;    Data : (SourceName: 'censored';  DestinationName: 'censored'; SourceValue: 'O'; DestinationValue: 'O')),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )), // Valeur Plus Significative que censored
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: TestConstSetter;    Data : (SourceName: 'censored';  DestinationName: 'censored'; SourceValue: 'O'; DestinationValue: 'A')),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: TestConstSetter;    Data : (SourceName: 'censored';  DestinationName: 'censored'; SourceValue: 'O'; DestinationValue: 'I')),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; )),
        (SetProc: StandardSetter;     Data : (SourceName: 'censored';  DestinationName: 'censored'; ))
      );
     
    procedure TfCensored.RecopieChampsEnCommun(Source, Destination: tEpcMyDataset);
    var
       iField: integer;
       iMapping: TSourceDestinationMapping;
    ...
       Editing: Boolean;
    begin
       Editing := Destination.State in [dsEdit, dsInsert];
       if not Editing then
         Destination.Edit; // Travail sur la ligne en cours
     
       // Ancienne ou Nouvelle Version de Source ?
       if (GetGlobal('Source', 'VER_SUP_0999', 'N') = 'O') then
       begin
          // Copie des Champs de la Table Source vers une Autre Table selon le Mapping
          for iMapping := Low(iMapping) to High(iMapping) do
            Source_MAPPING[iMapping].SetProc(Source_MAPPING[iMapping].Data, Source, Destination);
       end else
       begin
          // Ancien Mapping (Corrigé ? )
          for iField := 0 to Source.FieldCount - 1 do
          begin
             if Destination.FieldNum(Source.Fields[iField].FieldName) > 0 then
             begin
                if (Trim(Source.Fields[iField].AsString) <> '')
                and (Destination.FieldByName(Source.Fields[iField].FieldName).isNull
                  or (Trim(Destination.FieldByName(Source.Fields[iField].FieldName).AsString) = '')) then
                begin
                   if epcPos(Source.Fields[iField].FieldName, '...|...|...|...') then
                   begin
                      Destination.FieldByName(Source.Fields[iField].FieldName).AsString
                         := AnsiReplaceText(Source.FieldByName(Source.Fields[iField].FieldName).AsString, '.', '');
                   end else
                   begin
                      Destination.FieldByName(Source.Fields[iField].FieldName).AsString
                         := Source.FieldByName(Source.Fields[iField].FieldName).AsString;
                   end;
                end;
             end;
          end;
       end;
     
       // Calcul ...
     
       Destination.Post();
       if Editing then
          Destination.Edit();
    end;

  4. #24
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Non j'ai pas confondu record et class, j'ai oublié de le mettre dans la liste nouveautés Delphi 2005 ou Turbo Delphi ... (pour les record : procedures et fonctions membres, visibilité -public, private,... -, surcharge d'opérateurs ...).
    Et bien d'autres http://blog.developpez.com/index.php...&c=1&tb=1&pb=1

    Et oui une procedure of object c'est en interne un type TMethode, mais avec bien entendu de meilleurs contrôles à la compilation.

    D'ailleurs en débogage sur un FProcSurObjet = procedure of object; on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FProcSurObjet      ( Project1.TObjetDefProc.Test , $A0DA00 )
      |- Code             $408FE0 
      |- Data             $A0DA00
    Bon développement,

  5. #25
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 577
    Points : 25 225
    Points
    25 225
    Par défaut
    Oh, du Pseudo Objet dans les Record ??? en fait, un Record ça ne serait pas simplement un TObject déguissé genre "= record" et c'est comme "= class" en DELPHI 2005, ce qui ne serait pas surprenant puisque le file of record à été supprimé, et que la logique dot net tout protection bien chiante ne peut pas supporter la tricherie des record, copymemory ou autre ... avec D7, j'en suis bien loin, personnellement, je préfère éviter le Dot net, voulant aller dans l'industriel ou l'informatique bas niveau, je dois réapprendre le c\c++ et fuire le montre de MicroSoft qui fait en sorte de ne plus avoir de programmeur système en dehors des siens d'ici 40 ans (le business ça se planifie)

  6. #26
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    PS :
    Pour une solution objet il y avait aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    TSourceMappingData = class
      public
        SourceName : string;      // Champ dans la Table Source
        DestinationName: string;  // Champ dans la Table Destination
        SourceValue: string;      // Champ qui sera comparé au Champ Source
        DestinationValue: string; // Champ qui sera affecté au Champ Destination
        RelationName: string;     // Champ dans la Table Source qui sert pour un Test
        procedure MappingSetter( const Source, Destination: TDataSet) ;virtual; abstract;
      end;
     
      TSourceMappingDataSetter1 = class
      public
        procedure MappingSetter( const Source, Destination: TDataSet);
      end;
     
      TSourceMappingDataSetter2 = class
      public
        procedure MappingSetter( const Source, Destination: TDataSet);
      end;
    avec pour la création :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var SourceMappingArray : array[indices] of TSourceMappingData;
    ...
    SourceMappingArray[1] := TSourceMappingDataSetter1 .Create;
    SourceMappingArray[2] := TSourceMappingDataSetter2 .Create;
    SourceMappingArray[3] := TSourceMappingDataSetter1 .Create;
    ...
    mais la on ne peut plus changer la méthode après la création de l'objet (sauf transtypage sauvage TSourceMappingDataSetterX(Objet).MappingSetter, tenter de changer le pointeur de la Vtable )

  7. #27
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 577
    Points : 25 225
    Points
    25 225
    Par défaut
    La solution objet pose le problème du Create et du Free (il est indispensable en D7, en D2005, Garbage Collector à la Java\C# ?)

    le code est donc plus long, moins agréable à maintenir, je trouve ...

    Sinon, la VTable c'est du RTTI non ? donc c'est des constantes que l'on ne peut pas changer j'ai déjà voulu attaquer l'altération de SetProc d'un TPropInfo ... j'ai compris ensuite que c'était constant, cf http://www.developpez.net/forums/sho...d.php?t=264383

    pour le RTTI, ce sujet http://www.developpez.net/forums/sho...d.php?t=108779 peut être consulté ça donne une idée ...

  8. #28
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Les record restent alloués dans la pile (sauf si créé par new) et pas d'héritage possible ; c'est surtout du sucre syntaxique :
    au lieu d'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    TMonRecord = record
      ... 
    end;
     
    function TMonRecord_Ajouter ( const A,B : TMonRecord    ) : TMonRecord  ;
    ...
    MonRecord := TMonRecord_Ajouter ( A ,B );
    On peut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TMonRecord = record
      ... 
      function Ajouter ( const B : TMonRecord    ) : TMonRecord  ;
    end;
    ...
    MonRecord := A.Ajouter(B);
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TMonRecord = record
      ... 
      class operator Add ( const A,B : TMonRecord    ) : TMonRecord  ;
    end;
    ...
    MonRecord := A+B;
    Le code généré sera équivalent, c'est surtout une question de goût.

    Pour les objets, c'est toujours dans le tas ; il faut donc effectivement faire un free (en win32, pas de gc), c'est pour ça qu'il n'y a pas de surcharge d'opérateurs pour les objet en win32 (en .Net si). Les nouveaux Delphi font toujours la distinction entre win32 et .net (perso j'utilise Turbo Delphi win32) ;
    la compatibilité win32 est donc toujours assurée. Les ajouts de fonctionnalités ne se font que si cela est possible (interfaces implémentées par record, impossible sans gc (à cause gestion mémoire à la COM _addref ...) -> pas en win32).

    Enfin a propos du pointeur de la Vtable : c'était plus une blague qu'une suggestion d'implémentation la Vtable est propre à une classe (donc il ne faut pas y toucher car elle est partagée par les objets de la classe), mais chaque objet possède son propre pointeur vers celle de sa classe (et vouloir le modifier n'est assurément pas une bonne idée).

  9. #29
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 577
    Points : 25 225
    Points
    25 225
    Par défaut
    Effectivement, personnellement, je n'utilise quasimet QUE des pointeurs sur Structure lorsqu'il s'agit de stocker une collection de structure avec une TList

    sinon gb_68, on est pas tous en Delphi 2005, donc fait bien la distinction class et record en D7- car la surcharge d'opérateur ça n'existe que pour les variants (est c'est pas évident), les méthodes c'est que pour les objets ...

    vouloir modifier la Vtable n'est pas possible, mais la consulter est utile !

    Ce message a mis du temps à motiver les troupes mais ça fait débat entre nous trois ... lol

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. classe sans déclaration et pointeur de fonction
    Par Asmod_D dans le forum C++
    Réponses: 3
    Dernier message: 27/06/2010, 16h39
  2. structures et pointeurs de fonctions
    Par aimad41 dans le forum C
    Réponses: 5
    Dernier message: 21/11/2006, 10h49
  3. Structure, pointeur et fonction...
    Par Linaa dans le forum C
    Réponses: 15
    Dernier message: 04/12/2005, 13h12
  4. Pointeur de fonction et structure
    Par Trunks dans le forum C
    Réponses: 6
    Dernier message: 07/10/2005, 00h32
  5. Réponses: 4
    Dernier message: 08/02/2005, 20h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo