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 :

[Dll] Plugin et TComponent


Sujet :

Langage Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut [Dll] Plugin et TComponent
    J'ai une erreure recurente au cours de mon dev qui me perturbe un peu.
    A chaques fois je trouve uen astuce pour la contourner mais sans vraiement la resoudre.

    Le projet :
    Une dll exporte une classe type Plugin qui manipule divers objets de ma dll.
    L'ensemble des objets et du plugin est lié a ma classe exporté (Constructeur/Destructeur)

    Cette classe est exportee par une fonction GetPlugin et manipulee via son interface.

    L'exe lui implemente une classe descendant de TComponent pour plus tard y acceder depuis la palete d'outils Delphi.
    elle charge l'interface via la methode GetPlugin de la Dll et la stocke dans uen variable privee. Plusieurs methodes sont developpés pour acceder et appeler les methodes de l'inteface.

    Cette classe "composant" implemente une interface Events (sur les precedents conseils du Troll de developpez ) qu'elle transmet a la classe de la Dll via une methode SetEvents(Self).
    La classe dans la Dll manipule cette interface et donc les methodes de mon TComponent depuis uen variable interface qu'elle pense bien sur a mettre a nil lors de sa destruction.
    Apres verification l'affectaiton a nil d'une interface n'implique pas de destruction du TComponent contrairement a TInterfaceObject.

    Mon TComponent dans l'exe est actuelement cree dynamiquement mais possede pour owner la form de test. donc normalement se detruit lorsque la form se detruit, et ferme ainsi la dll.

    Le probleme
    Lorsque je ferme mon application, dans certains cas, j'ai une erreur si je ne fait pas de free sur mon plugin dans l'event OnCLose de ma form ....

    Ce qui semble poser un probleme dans mon application c'est la gestion des logs.
    Dans la Dll j'ai 2 classes : Tcore et TLogs. TLogs.OnAddLine utilise TCore.AddLineEvent comme gestionnaire.
    TCore.AddLineEvent(String) utilise l'interface Events pour appeler la methode AddLogLine(ShortString) stdcall de l'interface Events : IEvents,
    Dans l'exe ma classe TPlugin(TComponent, IVents) j'implemente AddLogLine(ShortString) qui appelle le gestionnaire utilisateur via DoAddLogLine(String).
    Dans ma Form J'ai donc une methode affectee dynamiquement a Mon Plugin lors du FormCreate : PluginAddLogLine(Sender, String) qui ajoute a une list box placée en mode design sur ma form.

    Pourquoi c'est les chaines de log lancées dans lors de la destruction du Plugin (TForm.Free -> TPlugin.Free -> |EXE<>DLL|-> TCore.Free -> TLog.Free) qui paralisent laissent l'applciation dans un etat "zombi" finissant par une exception.
    Lors de chaques free, je fais met bien tous mes pointeurs a Nil (interfaces, gestionnaires, etc ....)

    Si vous avez des pistes je peux poster du code plus precis
    Dans l'exe,

  2. #2
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Bon je viens de trouver mon probleme et je viens donc faire part de mon experiance ici a qui veux bien l'ecouter

    Donc mon probleme ne venait absolument pas de ma gestion Dll mais de la facon dont j'ai concu ma classe derivee de TComponent.

    Donc, Quand on creer une classe derrivee de TComponent, pour beneficier de la destruction automatique par le parent grace a la property "Owner" il faut eviter de toucher a un controle ou composant lors de la destruction.

    Dans mon cas, lorsque la fenetre principale se detruit, elle detruit les objets dont elle est le proprietaire dont entre autre mon TPlugin et une listBox qu'elle possede.
    Or lors de la destruction de mon TPlugin, je libere la Dll et tout ce qu'elle contient, generant ainsi des entree dans le log que je repercute dans l'applciation principale pour les afficher dans un TListBox.
    Au final, Mon TPlugin appelle donc un gestionnaire d'evenement de ma fenetre principale, qui a pour tache d'ajouter la ligne de log dans le TListBox.

    La ou ca coince c'est que ma form libere les objets dont elle est proprietaire dans un ordre indeterminé, du moins influance par l'ordre de creation des objets. (Plus precisement dans l'odre des affectation de la fenetre principale a la prop owner des composant)
    Donc MA form cree le ListBox en premier car il est defini en mode design, et mon plugin ensuite, car cree dynamiquement sur le FormCreate.
    Lors de la destruction automatisée des composant par la fenetre principale, on obtient en premier lieu la liberation du listbox puis de mon TPlugin.
    Dans ce cas, lors dela generation des derniers logs, le gestionnaire se retrouve a appeler un TListBox deja destruit ....

    Pour palier au probleme, j'ai du creer une property de type TListBox dans mon TPlugin qu'il manipule en interne (au lieu de passer par un gestionnaire d'evenement) qui me permet de tester avant d'ajouter une ligne de log si la property est a nil ou pas.

    Ensuite, la liberation de la list box par la fenetre principale ne repercute pas la valeur "Nil" a toutes les variable auquel elle a ete lié, dont notre property, ce qui reviens au meme que precedement.

    Il faut donc en plus surcharger la methode "Notification" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Procedure TTVPlugin.Notification(AComponent : TComponent; Operation : TOperation);
    Begin
    Inherited Notification(AComponent, Operation);
    If Operation = opRemove then
       Begin
       If AComponent = Self.FLogDisplay then Self.FLogDisplay := Nil;
       End;
    End;
    Pour affecter a Nil notre property TListBox quand cette derniere est liberee (par notification de la liberation de la part du TListBox)
    Et bien sur avertir le composant TListBox que l'on souhaite etre averti du moment ou ce dernier est libere :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Procedure TTVPlugin.SetLogDisplay(ALogDisplay : TListBox);
    Begin
    Self.FLogDisplay := ALogDisplay;
    If ALogDisplay <> Nil Then ALogDisplay.FreeNotification(Self);
    End;
    Cette fonction est lié a notre property en ecriture (Write).

    Avec ca ... plus de soucis
    Enfin ... si on prends le soin de tester la nullité de notre property avant d'appeler ses methodes

    Merci a tous ceux qui on pris du temps a me lire

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

Discussions similaires

  1. Nom de la dll via native-maven-plugin
    Par ejl07 dans le forum Maven
    Réponses: 10
    Dernier message: 28/06/2012, 09h35
  2. Conflit app.config avec dll plugin
    Par ppphil dans le forum C#
    Réponses: 4
    Dernier message: 12/08/2010, 16h49
  3. Réponses: 1
    Dernier message: 15/01/2007, 10h45
  4. DLL (plugin VST) en C++ avec Eclipse
    Par milou645 dans le forum C++
    Réponses: 1
    Dernier message: 24/11/2005, 16h28
  5. Réponses: 13
    Dernier message: 20/06/2005, 14h13

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