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

Langage Delphi Discussion :

Court circuiter le ref-count d'un TInterfacedObject!


Sujet :

Langage Delphi

  1. #41
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Imaginons que nous soignons dans un arbre. L'un des parents de cet arbre est manipulé par le biais d'une interface lors d'un traitement et possède une référence stockée dans ses enfants sous forme d'interface. Imaginons que ce parent se retrouve ne plus être utilisé par ses parents et par le programme, il devrait se libérer automatiquement. Sauf que ses enfants continuent à garder une référence de lui. Là vous avez une fuite mémoire. Pour ce faire il serait bien d'avoir un objet qui puisse stocker une interface sans pour autant incrémenter le ref-count de l'objet qui est stocké( référence faible comme dans le controller des TAggregatedObject). Pour ce faire je propose ceci :
    moi je comprend pas....(me faut peut être plus de café car j'ai vraiment du mal). si un parent d'une feuille est viré, alors tout le sous arbre avec cette feuille comme racine est viré aussi non...

    j'ai vraiment du mal.

  2. #42
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IMonInterface as IUneAutre
    je ne crois que l'on puisse faire ca.

    je crois que c'est forcement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      InstanceObj as Interface
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IUneAutre(InstanceObj)

  3. #43
    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 : 55
    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 448
    Points
    28 448
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    Ca marche mais c'est de la haute bidouille. Tu cast l'interface en pointeur pour tromper le compilateur pour qu'il n'appelle pas AddRef implicitement...



    C'est un truc sur lequel j'ai toujours eu un doute. D'un point de vu théorique, une interface c'est juste une déclaration de prototypes de méthodes.
    Sauf que l'implémentation qui en a été faite par Borland dans Delphi, c'est uniquement pour implémenter des objets COM.
    Ensuite ils ont détourné cette implémentation pour utiliser des interfaces sur autre chose.
    Donc ce que tu es en train de dire, c'est qu'en Delphi, toute interface dérive implicitement de IUnknown.

    Sinon Suryavarman, le comptage de référence a ces limites. Ce que tu veux c'est un garbage collector...
    oui, on peut dire qu'une interface c'est un tableau de pointeurs de méthode...c'est ce que je commence par expliquer dans le livre Delphi 7 Studio d'ailleurs

    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
     
    // page 517
    type
     IUnknown=^PUnknown;
     PUnknown=^TUnknown;
     TUnknown=record
      QueryInterface:function(constSelf:IUknown; const IID:TGUID; out obj):integer; stdcall;
      AddRef:function(const Self:IUnknown):integer; stdcall;
      Release:function(const Self:IUnknown):integer; stdcall;
     end;
     
    // et pour l'exemple de IDirectDraw
     IDirectDraw=^PDirectDraw;
     PDirectDraw=^TDirectDraw;
     TDirectDraw=record
     // IUnknown
      Unknown:TUnknown;
     // IDirectDraw
      Compact:function...
     end;
    mais le mot clé interface de Delphi est bien défini comme ceci :
    "
    The declaration of an interface can specify an ancestor interface. If no ancestor is specified, the interface is a direct descendant of IInterface, which is defined in the System unit and is the ultimate ancestor of all other interfaces. IInterface declares three methods: QueryInterface, _AddRef, and _Release.

    Note: IInterface is equivalent to IUnknown. You should generally use IInterface for platform independent applications and reserve the use of IUnknown for specific programs that include Windows dependencies.
    "

    c'est d'ailleurs une évidence puisque Delphi invoque automatiquement AddRef et Release lors de l'affectation d'une variable de type interface, et que l'opérateur AS correspond à QueryInterface.

  4. #44
    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 : 55
    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 448
    Points
    28 448
    Par défaut
    Citation Envoyé par Kaféine Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IMonInterface as IUneAutre
    je ne crois que l'on puisse faire ca.

    je crois que c'est forcement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      InstanceObj as Interface
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    IUneAutre(InstanceObj)
    pour reprendre mon code précédent, les deux lignes suivantes sont totalement équivalentes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var
     v1:IVersion1;
     v2:IVersion2;
    begin
     v2.QueryInterface(IVersion1,v1);
     v1:=v2 as IVersion1;
    end;
    alors que le code suivant à des chances de planter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     v2:=TVersion2.Create;
     IVersion1(v2).SayHello;
    en fait, comme je l'explique plus haut, les interfaces sont des tableaux de méthodes, si SayHello est la 5ième méthode de l'interface IVersion1, c'est la 5ième méthode de IVersion2 qui sera invoquée...en espérant qu'elle existe et qu'elle a les mêmes paramètres que SayHello !

  5. #45
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    ok je vois bien mais je que je voulais dire c'est que le queryinterface etait une securité:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    var
     v1:IVersion1;
     v2:IVersion2;
    begin
     v2.QueryInterface(IVersion1,v1);
     
     
    // v1:=v2 as IVersion1; pas besoin de ca si queryinterface  a reussi on
    // V1 <> nil
     
     if v1 <> nil then
        v1.methode..
    end;
    et ca

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    v2:=TVersion2.Create;
    IVersion1(v2).SayHello;
    alors t sur que v2 support IVersion1 ...... sans prendre de précaution

  6. #46
    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 : 55
    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 448
    Points
    28 448
    Par défaut
    Citation Envoyé par Kaféine Voir le message
    ok je vois bien mais je que je voulais dire c'est que le queryinterface etait une securité:

    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
     
    var
     v1:IVersion1;
     v2:IVersion2;
    begin
     v2.QueryInterface(IVersion1,v1);
     
     
    // v1:=v2 as IVersion1; pas besoin de ca si queryinterface  a reussi on
    // V1 <> nil
     
    // OUI JE DISAIS QUE LES LIGNES SONT IDENTIQUES !!!!
     
     if v1 <> nil then
        v1.methode..
    end;
    et ca

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    v2:=TVersion2.Create;
    IVersion1(v2).SayHello;
    alors t sur que v2 support IVersion1 ...... sans prendre de précaution
    c'est le principe du cast, sinon c'est "as" En fait on cast quand ON sait ce que le compilateur ne peut pas découvrir tout seul.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    procedure AppelerHello(obj:IInterface; versionObjet:integer);
    begin
     case versionObjet of
      1 : IVersion1(obj).Hello;
      2 : IVersion2(obj).Hello;
      3 : IVersion3(obj).Hello;
     end;
    end;
    maintenant il est toujours possible de coder comme ceci
    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
     
    procedure AppelerHello(obj:IInterface);
    var
     v1:IVersion1;
     v2:IVersion2;
     v3:IVersion3;
    begin
     v1:=obj as IVersion1;
     if v1<>nil then 
     v1.Hello 
     else begin
      v2:=obj as IVersion2;
      if v2<>nil then
      ...
     end;
    end;
    C'est aussi nécessaire quand le type d'origine n'est pas une interface (cast d'un pointer)

  7. #47
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    ok ... et bien je suis d'accord et je reprend un café....

    a la tienne

  8. #48
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    en fait, comme je l'explique plus haut, les interfaces sont des tableaux de méthodes, si SayHello est la 5ième méthode de l'interface IVersion1, c'est la 5ième méthode de IVersion2 qui sera invoquée...en espérant qu'elle existe et qu'elle a les mêmes paramètres que SayHello !
    Il faudrait préciser : Les interfaces de type VMT. Pour les interfaces dispatch (utilisées depuis les scripts ou en late-binding) ça n'a rien à voir.

    Microsoft détourne même le fonctionnement des interfaces dispatch dans ADO pour appeler les procédures stoquées d'une base de données comme s'il s'agissait de méthode de la connexion :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var cnt : OleVariant;
         ADOConnexion : TADOConnection;
    begin
      ...
      cnt := ADOConnection.Connection_;
      cnt.MaProcedureStockeeAMoi;
      ...
    Ca passe à la compile, et c'est censé fonctionner à l'exécution, si MaProcedureStockeeAMoi est le nom d'une procédure stockée dans la BDD.

    Bon c'est ce que dit la doc, j'ai jamais vérifié. Je n'aimes pas cette façon de faire.

    En même temps, est-ce qu'on peut considérer que les dispinterface sont encore des interfaces ?

  9. #49
    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 : 55
    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 448
    Points
    28 448
    Par défaut
    fait gaffe avec le petit café

  10. #50
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Haha excellent. j'en suis pas (encore) la

Discussions similaires

  1. [PageControl] Raccourcis claviers court-circuités
    Par Manopower dans le forum Composants VCL
    Réponses: 8
    Dernier message: 04/09/2009, 16h52
  2. [Disque Dur] Problème de court-circuit
    Par saih_tam dans le forum Composants
    Réponses: 9
    Dernier message: 20/05/2009, 15h03
  3. Réponses: 2
    Dernier message: 06/07/2007, 10h41
  4. Réponses: 13
    Dernier message: 09/04/2007, 13h20
  5. Réponses: 4
    Dernier message: 16/03/2004, 18h03

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