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 :

Pointer et conversion sur Self et TObject


Sujet :

Delphi

  1. #1
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut Pointer et conversion sur Self et TObject
    Bonjour

    Le code suivant me pose problème:

    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
     
    var
      Form7: TForm7;
     
    implementation
     
    {$R *.dfm}
     
    function Pt(Obj: TObject): NativeUint;
    begin
      Result := NativeUint(@Obj);
    end;
     
    procedure Comp(P: NativeUINT);
    var
      K: NativeUint;
    begin
      K := Pt(Form7);
      if P = K then
        ShowMessage( TForm7( Pointer(P)^ ).Name );
    end;
     
    procedure TForm7.FormCreate(Sender: TObject);
    var
      V1, V2: NativeUint;
    begin
      V1 := Pt(Self);
      V2 := Pt(Form7);
      Comp(V2);
    end;

    Dans le FormCreate, V1 et V2 sont égaux.
    Mais dans Comp, K est différent de P alors que je le récupère de la même façon que dans FormCreate

    Et là, je ne comprends pas pas trop le pourquoi du comment :-(

  2. #2
    Futur Membre du Club
    Profil pro
    Directeur technique
    Inscrit en
    Mai 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Mai 2005
    Messages : 4
    Points : 6
    Points
    6
    Par défaut
    Pour Delphi les objets sont en fait des pointeurs sur des objets. Il suffit de virer le @ devant obj et ça devrait fonctionner.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    function Pt(Obj: TObject): NativeUint;
    begin
      Result := NativeUint(Obj);
    end;

  3. #3
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 762
    Points : 957
    Points
    957
    Par défaut
    Citation Envoyé par Papy214 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
     
    procedure Comp(P: NativeUINT);
    var
      K: NativeUint;
    begin
      K := Pt(Form7);
      if P = K then
        ShowMessage( TForm7( Pointer(P)^ ).Name );
    end;
     
    procedure TForm7.FormCreate(Sender: TObject);
    var
      V1, V2: NativeUint;
    begin
      V1 := Pt(Self);
      V2 := Pt(Form7);
      Comp(V2);
    end;
    Il y a que moi que cela choque de travailler un coup avec un type NativeUInt d'un côté et un type Pointeur de l'autre ?

    Il me semble que ce code pourrais être simplifié en utilisant exclusivement des Pointeurs.

  4. #4
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    Oui, je sais, c'est bizarre mais j'ai une bonne raison de faire ça

    Je dois coder une classe qui reprend exactement les mêmes procédures avec les même paramètres qu'un activeX existant.
    Enfin, une partie seulement des fonctions, heureusement pour moi.
    Le but est de remplacer l'activex par mon objet sans toucher au code source du projet.

    Et plusieurs de ces fonctions utilisent un handle de type integer comme paramètre.
    Sauf que j'utilise un objet et non un TControl.
    Donc, pas de handle. Et pas le peine d'en créer un si je peux éviter.
    En interne, je peux utiliser n'importe quelle valeur entière.
    Chaque instance de la classe doit avoir un identificateur entier (comme si c'était son handle).
    Cet identificateur me sert dans un système de message pour faire communiquer les objets les uns avec les autres.
    D'abord, j'ai utilisé un compteur en variable de classe.
    Et je me suis dis que pour éviter ça, je pourrais simplement utiliser l'adresse de l'objet.
    Mais comme il me faut un entier, je caste l'adresse en entier et je passe cette valeur dans ma structure de message.
    à réception du message par l'instance correspondante, je me sers de la valeur que je caste à nouveau en pointer puis dans le type voulu pour pointer sur l'objet.

    Voili voilà !

  5. #5
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    Citation Envoyé par p.leali Voir le message
    Pour Delphi les objets sont en fait des pointeurs sur des objets. Il suffit de virer le @ devant obj et ça devrait fonctionner.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    function Pt(Obj: TObject): NativeUint;
    begin
      Result := NativeUint(Obj);
    end;
    Oh le voilà ! Bienvenue !

    J'essaye demain. Le vpn est cassé depuis 2 jours et le bureau est inaccessible depuis chez moi.

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Result := NativeUint(@Obj) ne peut pas fonctionner. @Obj est un pointeur sur la variable Obj locale à la fonction et non son contenu.

    V1 et V2 sont égaux parce qu'une variable locale est désallouée à la sortie de la fonction. Le deuxième appel immédiat à Pt peut donc réutiliser la même adresse que le premier pour sa variable Obj.
    Dans Comp, ça ne joue plus puisque cette fonction a également un paramètre. C'est ce paramètre P qui sera à l'adresse du Obj précédent (tu peux contrôler, P = @P). A l'appel de Pt depuis Comp, Obj sera décaler sur la pile

  7. #7
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    Paul : Effectivement, ça fonctionne avec le code suivant :

    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
     
    function Pt(Obj: TObject): NativeUint;
    begin
      Result := NativeUint(Obj);
    end;
     
    procedure Comp(P: NativeUINT);
    var
      K: NativeUint;
    begin
      K := Pt(Form7);
      if P = K then
        ShowMessage( TForm7( Pointer(K) ).Name );
    end;
     
    procedure TForm7.FormCreate(Sender: TObject);
    var
      V1, V2: NativeUint;
    begin
      V1 := Pt(Self);
      V2 := Pt(Form7);
      Comp(V2);
    end;

    Andnotor :

    Je ne comprends pas ton raisonnement. V1 et V2 contiennent l'adresse (convertie en entier) de mon TForm.
    Les 2 variables contiennent la même valeur puisque j'appelle 2 fois la fonction sur le même objet dénommé de 2 manières différentes.
    Dans Comp, le résultat de la fonction devrait donner la même valeur puisque puisque j'appelle la fonction de la même façon.
    Enfin, il me semble

  8. #8
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Result := NativeUint(@Obj) ne peut pas fonctionner. @Obj est un pointeur sur la variable Obj locale à la fonction et non son contenu.

    V1 et V2 sont égaux parce qu'une variable locale est désallouée à la sortie de la fonction. Le deuxième appel immédiat à Pt peut donc réutiliser la même adresse que le premier pour sa variable Obj.
    Dans Comp, ça ne joue plus puisque cette fonction a également un paramètre. C'est ce paramètre P qui sera à l'adresse du Obj précédent (tu peux contrôler, P = @P). A l'appel de Pt depuis Comp, Obj sera décaler sur la pile
    ou alors, tu veux dire que dans ma fonction, P est un pointer sur un pointer ?

  9. #9
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Citation Envoyé par Papy214 Voir le message
    Je ne comprends pas ton raisonnement. V1 et V2 contiennent l'adresse (convertie en entier) de mon TForm.
    Pas avec @Obj, c'est l'adresse de Obj qui est retournée et non son contenu. Tu peux appeler Pt() sur n'importe quoi, même nil si tu veux, tu auras toujours le même résultat

    Citation Envoyé par Papy214 Voir le message
    ou alors, tu veux dire que dans ma fonction, P est un pointer sur un pointer ?
    C'est ça, Obj est une variable pointeur typé. @Obj est un pointeur sur cette variable de type pointeur

  10. #10
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 762
    Points : 957
    Points
    957
    Par défaut
    Citation Envoyé par Papy214 Voir le message
    Oui, je sais, c'est bizarre mais j'ai une bonne raison de faire ça

    Je dois coder une classe qui reprend exactement les mêmes procédures avec les même paramètres qu'un activeX existant.
    Ah, si tu as des contraintes externes, c'est différent, je retire ce que j'ai dit

  11. #11
    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 430
    Points
    28 430
    Par défaut
    Citation Envoyé par der§en Voir le message
    Ah, si tu as des contraintes externes, c'est différent, je retire ce que j'ai dit
    il reste possible de gérer un index dans une liste, on un dictionnaire Index->Objet qui permet de vérifier la validité de l'objet avant de l'utiliser...mais l'usage d'un THandle pour stocker un objet est tout à fait valide
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  12. #12
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    il reste possible de gérer un index dans une liste, on un dictionnaire Index->Objet qui permet de vérifier la validité de l'objet avant de l'utiliser...mais l'usage d'un THandle pour stocker un objet est tout à fait valide
    C'est ce que j'avais fait au départ. Un simple compteur en variable de classe incrémenté à chaque création d'objet et qui donnait un id différent pour chaque instance.
    La solution était simple et tout à fait conforme à l'usage que je voulais en faire.
    Ça fonctionnait très bien mais je trouvais ça superflu si je pouvais utiliser l'adresse de l'objet lui-même.

    Comment aurais-tu fait dans un cas pareil ? Utilisation du compteur ou utilisation de l'adresse de l'objet ?

  13. #13
    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 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Papy214 Voir le message
    C'est ce que j'avais fait au départ. Un simple compteur en variable de classe incrémenté à chaque création d'objet et qui donnait un id différent pour chaque instance.
    La solution était simple et tout à fait conforme à l'usage que je voulais en faire.
    Ça fonctionnait très bien mais je trouvais ça superflu si je pouvais utiliser l'adresse de l'objet lui-même.

    Comment aurais-tu fait dans un cas pareil ? Utilisation du compteur ou utilisation de l'adresse de l'objet ?
    je crois que la dernière fois que j'ai eut à faire ce genre de chose j'utilisais directement le pointeur objet, mais je gardais dans un TList toutes les instances susceptibles d'être exploitées afin de vérifier que l'objet soit valide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function UtiliseObject(Obj: TMonObject): Integer; 
    begin
      if MaListe.IndexOf(Obj) < 0 then
      Exit(-1);
      Result := Obj.Fonction();
    end;
    l'autre approche fonctionne aussi mais complique la gestion de la liste

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    function UtiliseObject(Handle: THandle): Integer;
    var
      Obj: TMonObject;
    begin
      if (Handle < 0) or (Handle >= MaList.Count) then
       Exit(-1);
      Obj := MaList[Handle];
      if Obj = nil then 
      Exit(-1);
      Result := Obj.Fonction();
    end;
    quand un objet est détruit MaList est forcé à nil s'il existe des objets avec un Index plus grand afin de ne pas changer l'index des objets dans la liste
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #14
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 385
    Points : 2 999
    Points
    2 999
    Par défaut
    Ta solution est plus complète que la mienne mais dans mon cas, j'ai forcément un id de l'objet qui va recevoir le message.
    Et si le handle n'existe plus, de toutes façons, le message ne sera pas traité.

    Si à l'avenir je devais prendre en compte le problème que tu décris, je m'inspirerai de ta méthode.

    Merci

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

Discussions similaires

  1. Problèmes de conversion sur SelectOneMenu
    Par Pakiam dans le forum JSF
    Réponses: 7
    Dernier message: 13/08/2009, 17h03
  2. Faire pointer mon domaine sur un autre domaine
    Par ren0 dans le forum Serveurs (Apache, IIS,...)
    Réponses: 1
    Dernier message: 16/08/2008, 11h15
  3. Faire pointer le classpath sur des fichiers du jar
    Par Adriano1664 dans le forum Général Java
    Réponses: 2
    Dernier message: 29/04/2008, 11h05
  4. [BO XIR2]Conversion sur Desktop Intelligence
    Par perrine1985 dans le forum Deski
    Réponses: 2
    Dernier message: 15/04/2008, 13h34
  5. MSN Récupérer Conversation sur Autre Poste
    Par FloLens dans le forum Messagerie instantanée
    Réponses: 3
    Dernier message: 28/09/2007, 13h56

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