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

Composants VCL Delphi Discussion :

Utilisation de GetPropValue dans une DLL


Sujet :

Composants VCL Delphi

  1. #1
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut Utilisation de GetPropValue dans une DLL
    Bonjour,
    Je réalise une DLL en Delphi 6 Personal Edition. Dans le contexte d'une des fonctions que je suis en train de réaliser, je souhaite accéder, en lecture et en écriture, aux propriétés des objets VCL du programme appelant (réalisé également en Delphi, mais selon toute probabilité avec une autre version du VCL). Pour cela, le programme appelant passe l'objet VCL en paramètre, et je dois travailler avec dans la DLL.

    J'ai bien réalisé que, du fait des versions différentes des VCL, je ne peux pas simplement utiliser les propriétés et méthodes de l'objet passé en paramètre, car cela provoque en général une violation de mémoire. J'en conviens, c'est normal.

    Alors, j'ai essayé la fonction GetPropValue (en ajoutant TypInfo dans les clauses Uses). Pour tester la lecture d'une propriété, j'ai créé la fonction suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function TestGetProp(obj: TObject; propriete: pstring):integer; stdcall; export;
    var
      rep: variant;
    begin
      rep := GetPropValue(obj,propriete^);
      showmessage(rep);
      rep := Unassigned;
      result := 0;
    end;
    Cela marche parfaitement pour toutes les propriétés retournant une valeur entière (Left, Width, RowCount pour un TSTringGrid etc). Mais il y a un problème dès que la fonction GetPropValue retourne un variant de type varString (j'ai vérifié !). En fait, la valeur retournée est correcte (comme pour des propriétés Caption etc), et la fonction se termine normalement, sans erreur apparente. Mais, lorsque le programme principal s'arrête, la fenêtre ouverte disparaît bien visuellement, mais le processus reste en mémoire (vérifié par le gestionnaire des tâches, onglet Détails), et il faut le tuer manuelement. Sinon, impossible de le relancer, et de toutes façons, ou bout d'un temps variable, j'ai un message "Runtime Error 216".

    J'en déduis qu'il y a oue ressource quelconque qui n'est pas libérée, mais je n'arrive par à voir laquelle. C'est la raison d'ailleurs pour laquelle j'ai "détaillé" le code indiqué ci-dessus. Initialement, j'avais simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function TestGetProp(obj: TObject; propriete: pstring):integer; stdcall; export;
    begin
      showmessage(GetPropValue(obj,propriete^));
      result := 0;
    end;
    (la ligne "result := 0" tient aux conventions d'appel imposées par le programme appelant). Je constate que même la ligne "rep := "Unassigned" ne résoud pas le problème.

    Question: qu'est-ce que j'ai manqué ?

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Bonjour,

    Le problème principale de l'utilisateur d'un objet Delphi depuis une DLL vient du gestionnaire de mémoire.

    même avec exactement le même version de compilateur entre l'exe et le dll, il faut obligatoirement utiliser ShareMEM (ou FastMM si mon souvenir est bon) pour que les deux exécutables partages le même gestionnaire de mémoire et qu'un objet alloué par l'un puisse être libéré par l'autre.

    sur des objets cela semble évidement, mais c'est également la cas sur tout ce qui est alloué automatiquement comme les string et les tableau dynamiques, et probablement ici un Variant. C'est de là que vient l'usage des PChar en lieu est place des String afin de s'assurer que Delphi ne cherchera pas à modifier la chaînes (un "const propriete: string" fonctionnera aussi ceci dit)

    Ce que tu cherches à faire reste envisageable (bien que la structure des RTTI n'est pas garantie identique d'une version à l'autre) mais en s'assurant de faire un accès en lecture seule aux informations, cela passera probablement par la réécriture de la fonction GetPropValue().
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Merci d'avoir regardé mon problème.

    Réécrire GetPropValue ? Cette fonction faitbpartie de TypInfo, et avec Delphi 6 PE, je n'ai bien sûr pas les sources de ces modules. Il n'y a que le DCU.

    Je vois bien que ce ne sont pas les paramètres passés à cette fonction qui sont en cause, puisque ça marche parfaitement avec des propriétés retournant des valeurs entières. C'est bien l'allocation de la valeur de retour qui pose problème. Et elle se fait dans la DLL, puisque l'appel est émis de la DLL, non ?

    Et utiliser un des gestionnaires de mémoire - je veux bien, mais comment assurer la cohérence avec ce qui se passe dans le programme appelant ?

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    bien que la structure des RTTI n'est pas garantie identique d'une version à l'autre
    Il faut aussi utiliser les BPL partagés par l'EXE et DLL pour que les informations de type soient compatible, on le voit quand on affecte la Form de l'Exe comme parent à un Panel d'une Dll qui utilise ParentFont et que l'on obtient le message "TFont n'est pas assignable à TFont" parce que la DLL et EXE contiennent chacune une variante de TFont
    En mode BPL, les deux partages le TFont du package

    Essaye GetStrProp pour voir si c'est mieux que GetPropValue par contre, faut gérer les types à la main, voici un code que j'ai écrit pour refactoré 150 lignes de codes d'un développeur qui est parti d'où je travaille qui n'a jamais réussi à mettre en place les RTTI dans son projet

    GetPropValue encapsule aussi les appels à GetOrdProp, GetFloatProp, GetStrProp et de quelques autres types
    GetStrProp utilise le TPropInfo.GetProc qui contient soit un pointeur sur le membre (commence par $FF00....) soit un accesseur
    C'est à ce moment qu'au lieu de tenter de choper en type string, tu dois le gérer en PChar


    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
      procedure FillSubItemFromObjectAndParam(AViewItem: TListItem; AObjectRef: THOImportRef; const AParam: TParamStructInfo);
      var
        LPropInfo: System.TypInfo.PPropInfo;
        LIntValue: Integer;
        LFloatValue: Extended;
        LDateTimeValue: TDateTime;
      begin
        LPropInfo := TSliteRTTI.GetPropertyInfo(AObjectRef.ClassType(), AParam.Name);
        if Assigned(LPropInfo) then
        begin
          case LPropInfo^.PropType^.Kind of
           System.TypInfo.tkInteger :
            if AParam.DataType = ftInteger then
            begin
              LIntValue := System.TypInfo.GetOrdProp(AObjectRef, AParam.Name);
              AViewItem.SetSubItemByParamName(AParam.Name, IfThen(LIntValue <> DB_NUMBERNULL, IntToStr(LIntValue), ''));
            end
            else
              raise EDBHOFieldException.CreateFmt(rsFieldName_PublishedWithUnsupportedType, [AParam.Name], Self);
     
           System.TypInfo.tkEnumeration :
            if (AParam.DataType = ftInteger) and (System.TypInfo.GetTypeData(LPropInfo^.PropType^)^.BaseType^ = TypeInfo(Boolean)) then
              AViewItem.SetSubItemByParamName(AParam.Name, BooleanToStr(LongBool( System.TypInfo.GetOrdProp(AObjectRef, AParam.Name))))
            else
              raise EDBHOFieldException.CreateFmt(rsFieldName_PublishedWithUnsupportedType, [AParam.Name], Self);
     
           System.TypInfo.tkFloat :
            if AParam.DataType = ftFloat then
            begin
              LFloatValue := System.TypInfo.GetFloatProp(AObjectRef, AParam.Name);
              AViewItem.SetSubItemByParamName(AParam.Name, IfThen(LFloatValue <> DB_NUMBERNULL, FloatToStr(LFloatValue), ''));
            end
            else if AParam.DataType = ftDate then
            begin
              LDateTimeValue := System.TypInfo.GetFloatProp(AObjectRef, AParam.Name);
              AViewItem.SetSubItemByParamName(AParam.Name, IfThen(LDateTimeValue <> DB_DATENULL, DateToStr(LDateTimeValue), ''));
            end
            else if AParam.DataType = ftDateTime then
            begin
              LDateTimeValue := System.TypInfo.GetFloatProp(AObjectRef, AParam.Name);
              AViewItem.SetSubItemByParamName(AParam.Name, IfThen(LDateTimeValue <> DB_DATENULL, DateTimeToStr(LDateTimeValue), ''));
            end
            else
              raise EDBHOFieldException.CreateFmt(rsFieldName_PublishedWithUnsupportedType, [AParam.Name], Self);
     
           System.TypInfo.tkUString :
            if AParam.DataType = ftString then
              AViewItem.SetSubItemByParamName(AParam.Name, System.TypInfo.GetStrProp(AObjectRef, AParam.Name))
            else
              raise EDBHOFieldException.CreateFmt(rsFieldName_PublishedWithUnsupportedType, [AParam.Name], Self);
          else
            raise EDBHOFieldException.CreateFmt(rsFieldName_PublishedWithUnsupportedType, [AParam.Name], Self);
          end;
        end
        else
          raise EDBHOFieldException.CreateFmt(rsFieldName_NotPublished, [AParam.Name], Self);
      end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    Merci d'avoir regardé mon problème.

    Réécrire GetPropValue ? Cette fonction faitbpartie de TypInfo, et avec Delphi 6 PE, je n'ai bien sûr pas les sources de ces modules. Il n'y a que le DCU.

    Je vois bien que ce ne sont pas les paramètres passés à cette fonction qui sont en cause, puisque ça marche parfaitement avec des propriétés retournant des valeurs entières. C'est bien l'allocation de la valeur de retour qui pose problème. Et elle se fait dans la DLL, puisque l'appel est émis de la DLL, non ?

    Et utiliser un des gestionnaires de mémoire - je veux bien, mais comment assurer la cohérence avec ce qui se passe dans le programme appelant ?
    ah oui sans les sources c'est plus compliqué

    alors il faudrait creuser, mais tu as probablement à un moment donné un pointeur vers une chaîne allouée par l'exe donc le compteur de référence a été augmenté. Quand la DLL cherchera à la supprimer, c'est là que le gestionnaire de mémoire va partir en vrille.

    ce que tu peux faire c'est, en cas de String, regarde le Refcount de la chaîne, s'il est à 1 c'est mal, car l'exe en a fait une copie qu'il te confie et dont tu vas devoir gérer la durée de vie alors que ce n'est pas toi le gestionnaire.
    S'il est > 1 c'est parfait, tu en fais une copie et tu n'y touches plus.

    dans l'ordre
    1) le variant récupère la string en augmentant son RefCount
    2) tu copies la chaîne dont le RefCount ne change pas
    3) la variant ibère la chaîne = diminue le RefCount qui ne tombe pas à 0
    4) quand l'exe n'aura lui-même plus besoin de la chaîne il la libérera sans erreur puisqu'il en est propriétaire.

    ça doit pouvoir fonctionner
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Bonsoir,

    Merci beaucoup pour ces explications. J'en ai déduit ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function TestGetProp(obj: TObject; prop: pstring):integer; stdcall; export;
    var
      rep: variant;
      s: string;
    begin
      rep := GetPropValue(obj,prop^);
      if (VarType(rep) and VarTypeMask)=varString then s := rep;
      showmessage(rep);
      rep := Unassigned;
      result := 0;
      exit;
    end;
    Résultat: tout fonctionne normalement (évident: l'affectation d'une variable string ne change rien dans l'immédiat). Mais en arrêtant le programme, ça change: la fenêtre principale disparaît immédiatement, le processus reste encore actif 5 ou 6 seconds, puis disparaît de la liste du gestionnaire des tâches. Je n'ai plus de "runtime error". Apparemment, l'ajout de l'affectation de la variable string en cas de type varString a réglé le problème.

    Mais je vois que ShaiLeTroll a posté une procédure alternative. Je vais la tester maintenant.

  7. #7
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    @ShaiLeTroll:

    J'essaie de tester ton code, mais j'ai un problème: les symboles THOImportRef et TParamStructInfo sont inconnus dans mon Delphi 6 PE. Une recherche Google sur ces termes ne donne absolument rien.

    Question: d'où ça sort ?

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    C'était un exemple de lorsque l'on veut réécrire GetPropValue, juste un exemple, trop de dépendance à un code d'un ancien développeur qui avait l'idée des RTTI mais n'a pas eu la capacité des les utiliser

    Oubli mon idée de passer par TPropInfo.GetProc si la proposition d'une variable locale fonctionne,
    c'est bien mais ce qui me choque c'est qu'il ne considère pas cela comme une ligne inutile et qu'il ne l'a compile pas puisque que dans ton code

    EDIT : je ne savais pas !
    - Quand c'est un entier que l'on affecte pour rien : H2077 La valeur affectée à 'i' n'est jamais utilisée
    - Quand c'est une chaine que l'on affecte pour rien : il ne dit rien

    Est-ce que ceci fonctionne ?
    Disons qu'à long terme, le code semblera moins douteux (une affectation bidon c'est un peu le piège à la con)
    Citation Envoyé par KlausGunther Voir le message
    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
    function TestGetProp(obj: TObject; prop: pstring):integer; stdcall; export;
    var
      rep: variant;
      s: string;
    begin
      rep := GetPropValue(obj,prop^);
      if (VarType(rep) and VarTypeMask)=varString then
      begin
        s := rep;
        showmessage(s); // j'aurais plutôt mis cela pour que s soit utilisé
      end
      else
         showmessage(rep);
     
      rep := Unassigned;
      result := 0;
      exit;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Merci pour ton avis, ShaiLeTroll.

    Je ne vois pas bien la différence entre
    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
    function TestGetProp(obj: TObject; prop: pstring):integer; stdcall; export;
    var
      rep: variant;
      s: string;
    begin
      rep := GetPropValue(obj,prop^);
      if (VarType(rep) and VarTypeMask)=varString then
      begin
        s := rep;
        showmessage(s); // j'aurais plutôt mis cela pour que s soit utilisé
      end
      else
         showmessage(rep);
     
      rep := Unassigned;
      result := 0;
      exit;
    end;
    et mon code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function TestGetProp(obj: TObject; prop: pstring):integer; stdcall; export;
    var
      rep: variant;
      s: string;
    begin
      rep := GetPropValue(obj,prop^);
      if (VarType(rep) and VarTypeMask)=varString then s := rep;
      showmessage(rep);
      rep := Unassigned;
      result := 0;
    end;
    Je n'affecte la variable s$ que si la condition est remplié (retour en format de string variable...)

  10. #10
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Dans le fonctionnement les deux codes sont identiques

    Mais à la lecture du tien j'aurai tendance, comme premier réflex, à supprimer la condition et la variable S car affectée mais non utilisée

    Alors qu'à la lecture du code modifié par ShailLeTroll on voit bien que S est affecté et utilisé
    et là le premier réflex serait plutôt de tester pour comprendre le pourquoi de ce choix.

    Cordialement,
    @+

  11. #11
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Bien sûr que j'ai testé. Je ne suis pas borné et toujours curieux d'apprendre quelque chose.

    Evidemment, le code proposé par ShaiLeTroll fonctionne. Ce n'est pas la question. Le mien fonctionne aussi.... La seule différence entre les deux, c'est l'utilisation de la variable s dans le code de ShaiLeTroll alors qu'elle n'est pas utilisée dans le mien. Mais les deux fonctionnent.

    Mais: si je retire la création et l'affectation à la variable s, c'est là que j'ai le plantage. C'est bien l'affectation à s qui fait fonctionner le schmilblic et non l'utilisation de cette variable. C'est cela qui me posait question.

    Et tout cas, l'idée de Paul Toth d'utiliser une variable string m'a permis de débloquer la situation, même si je n'ai malheureusement pas tout compris. Mais à la limite, c'est secondaire. Je suis content et reconnaissant d'avoir une solution, et je vais marquer le sujet comme résolu.

  12. #12
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    je pense que je me suis mal exprimé

    je mets rien en cause ni le code de l'un ni de l'autre et j'ai bien compris son fonctionnement avec l'astuce de Paul

    l'envie de tester n'était pas pour toi mais pour moi ou tout autre lecteur.

    Je dis juste que la différence entre les deux codes est pour le futur lecteur du code

    et que dans la peau du futur lecteur qui lis ton code, en l'état et sans commentaire, le premier réflex est de penser que la condition est inutile
    (surtout si on ne connait pas cette astuce) ... tout le monde sait qu'une variable affectée et non utilisée est normalement écartée par le compilateur !!
    Mais Paul nous a démontré le contraire en ce qui concerne les strings.

    et dans les même conditions à la lecture du code de Shail on a pas ce réflex parce que S est utilisé

    C'est tout

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par Cirec Voir le message
    Mais à la lecture du tien j'aurai tendance, comme premier réflex, à supprimer la condition et la variable S car affectée mais non utilisée
    C'est exactement cela !

    Citation Envoyé par Cirec Voir le message
    l'envie de tester n'était pas pour toi mais pour moi ou tout autre lecteur.
    Cela peut être aussi pour lui dans deux ans quand il aura oublier le pourquoi du comment
    Et le jour où un autre développeur reprend le code, c'est sympa un code compréhensible


    C'est plus pour la forme, pour garantir un code lisible à long terme et le bon code serait plutôt le suivant (le commentaire étant le plus important en réalité)
    Comme ca, tu assures une maintenabilité du code
    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
     
     
    function TestGetProp(obj: TObject; prop: pstring):integer; stdcall; export;
    var
      rep: variant;
      s: string;
    begin
      rep := GetPropValue(obj,prop^);
      // Pour un Variant Chaine, gestion spéciale, 
      // Pour les autres types, utilisations directes et une conversion en chaine implicite 
      if (VarType(rep) and VarTypeMask)=varString then
      begin
        // Copie de la chaine du Variant dans une chaine locale pour éviter des problèmes avec le gestion de mémoire qui produira une Violation d'accès à la libération de la chaine en fin de programme sous la forme d'un "Runtime Error 216"
        // Rappel : https://www.developpez.net/forums/d1650479/environnements-developpement/delphi/composants-vcl/utilisation-getpropvalue-dll/#post9024198
        s := rep;
        showmessage(s); 
      end
      else
        showmessage(rep);
     
      rep := Unassigned;
      result := 0;
      exit;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  14. #14
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Certes. Tu as raison: pour la maintenabilité du code, il faut documenter cela correctement dans les commentairs. De toutes façons, tout cela fait partie d'un ensemble negttement plus vaste - j'avais juste extrait la partie minimale de mon code permettant de reproduire le phénomène. Le n'aime pas beaucoup publier une usine à gaz losque le demande de l'aide - je trouve qu'il est plus efficace de réduire le code à son stricte minimum nécessaire. Mais, oui, je vais documenter cela correctement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utiliser OLE COM dans une DLL
    Par andrebernard dans le forum C++
    Réponses: 5
    Dernier message: 20/05/2008, 18h01
  2. Utilisation de THTTPRIO dans une dll
    Par jv2759 dans le forum Composants VCL
    Réponses: 1
    Dernier message: 11/10/2007, 15h54
  3. Utiliser les MFC dans une dll
    Par simoryl dans le forum MFC
    Réponses: 4
    Dernier message: 10/09/2007, 09h16
  4. utilisation de classe dans une DLL
    Par _stef_ffff_f34 dans le forum Windows
    Réponses: 1
    Dernier message: 10/02/2006, 16h03
  5. Réponses: 7
    Dernier message: 25/11/2005, 17h11

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