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 :

Erreur à la fermerture du exe qui appelle une DLL


Sujet :

Delphi

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut Erreur à la fermerture du exe qui appelle une DLL
    Bonjour,

    Le titre résume bienle problème.


    J'appel une dll depuis un exe et lorsque je ferme l'exe j'ai le trap suivant :

    RunTime 216 at 00543A92

    Noter que ce problème se manifeste lorsque le code est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Procedure AFFICHE_NEW_NOTE(ParentApplication: TApplication;
                             ParentMDIFORM:TFORM;
                             ParentDATABASE:My_T_DATABASE;
                             ParentSESSION:MY_T_SESSION_TRANSACTION;
                             PTR_WORK_DLL:T_WORK); export;stdcall;
    begin
     
          My_DATABASE := ParentDATABASE;
          MY_SESSION_TRANSACTION[1].MY_Transaction := ParentSESSION.MY_Transaction;
          PTR_WORK:=PTR_WORK_DLL;
          MY_NOTES_LANCEUR.LANCER_NOTES_FORM
    end;
    Par contre il n'y a pas de problème lorsque le code est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Procedure AFFICHE_NEW_NOTE(ParentApplication: TApplication;
                             ParentMDIFORM:TFORM;
                             ParentDATABASE:My_T_DATABASE;
                             ParentSESSION:MY_T_SESSION_TRANSACTION;
                             PTR_WORK_DLL:T_WORK); export;stdcall;
    begin
     
          My_DATABASE := ParentDATABASE;
          MY_SESSION_TRANSACTION[1].MY_Transaction := ParentSESSION.MY_Transaction;
          MY_NOTES_LANCEUR.LANCER_NOTES_FORM
    end;
    vous aurez remarquer que la différence est PTR_WORK:=PTR_WORK_DLL;
    Sachant que PTR_WORK est une zone de travail utilisé dans l'exe, initialisation de varaible, de flag etc..

    l'appel de ma dll est statique et comme ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Begin
    PTR_WORK.Flag1 := 1;
    PTR_WORK.Flag2 := 2;
    PTR_WORK.Flag3 := 3;
    PTR_WORK.Flag4 := 4;
    PTR_WORK.Flag5 := 5;
     
    AFFICHE_NEW_NOTE(application,PTR_WORK.PARENT_MDIFORM,My_DATABASE,MY_SESSION_TRANSACTION[1],PTR_WORK);
    End;
    Merci de votre aide;

  2. #2
    Membre chevronné
    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
    Points : 2 158
    Points
    2 158
    Par défaut
    Quand on ferme une Dll, il faut cloturer toutes les references Exe->Dll et inversement.

    Je ne connait pas la ligne de code quetu enonce, mais si c'ets : Sachant que PTR_WORK est une zone de travail utilisé dans l'exe, initialisation de varaible, de flag etc.. alors ca correspond a ca.

    L'exe doit continuer a manipuler une zone memoire qui a ete liberee avec la fermeture de la Dll.

    PRends donc soit a liberer cette zone ou du moins les references avant de cloturer ta dll

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    merci, je me doutais de quelque chose comme cela, je vai étudier la chose,

    cordialement

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    Bonjour,

    Auriez-vous une doc ou un site qui pourrait eventuellement m'expliquer cette notion de libération.

    Je pense à free(PTR_WORK), ou dispose(PTR_WORK),

    Sachant que PTR_WORK est défini comme ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    T_WORK = Record
    Flag1:boolean;
    Flag2:boolean;
    Flag3:boolean;
    Flag4:boolean;
    End
    var
    PTR_WORK : T_WORK;
    En fait l’exe et la dll utilise tous les deux ptr_work qui est déclarer dans ma UNit Uvariables où Uvariables est en uses dans mon exe et dans ma Dll (c'est peut être là le problème) car je pense que ptr_work est « instancié» 2 fois, une fois lorsque l’exe est lancer et une fois lorsque la dll est charger (en fait je ne sais pas, je suppose, je ne maitrise pas cette notions).


    L'exe doit continuer a manipuler une zone memoire qui a ete liberee avec la fermeture de la Dll.
    En fait je veux toujours travailler avec cette zone de working, pouvez-vous me conseiller sur la facon de passer cette structure pour que cette derniere soit utiliser dans la DLL et "rendu" à l'exe pour la bonne continuation du travail

    Cordialement

  5. #5
    Membre chevronné
    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
    Points : 2 158
    Points
    2 158
    Par défaut
    Si je ne m'abuse, Dll et Exe partagent la meme zone memoire.
    Donc que la variable soit cree depuis le Dll ou l'exe elles se situent dans la meme zone memoire donc accessible d'un cote comme de l'autre.

    De ce fait, il suffit juste de transmettre l'adresse de cette variable pour que l'autre module sache ou et comment y acceder.
    Avec le type (pour savoir comment lire) et l'adresse (pour savoir a partir d'ou commencer a lire) on peux retrouver les données saisie par l'autre module.

    Donc quand tu dois transmettre une valeur, tranmet un pointeur sur cette valeur.

    Sinon, le probleme ne viens pas de la declaration des variables en elle meme, mais de leur utilisation.

    Si c'est la Dll qui cree le pointeur, quand la dll est liberee, elle libere les variables qu'elle a cree, donc toute autre reference a cette zone memoire situé dans un autre module deviens erroné.
    Donc il ne faut plus y faire appel.

    De plus, je ne puis l'affirmer, mais il est possible que tant qu'il existe une reference sur une zone memoire, la dll ne pourra pas liberer cette zone. En tout cas c'ets le cas avec les interfaces ...

    apres, la je ne maitrise pas trop le sujet .... si tu as des question essaye toujours

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    Merci bcp de ces précisions, en résumé il est préférable d'utiliser un pointer sur ma structure:

    le code de ma Dll déviendrai alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    Procedure AFFICHE_NEW_NOTE(ParentApplication: TApplication;
                             ParentMDIFORM:TFORM;
                             ParentDATABASE:My_T_DATABASE;
                             ParentSESSION:MY_T_SESSION_TRANSACTION;
                             PTR_WORK_DLL:Pointer); export;stdcall;
    begin
     
          My_DATABASE := ParentDATABASE;
          MY_SESSION_TRANSACTION[1].MY_Transaction := ParentSESSION.MY_Transaction;
          PTR_WORK:=PTR_WORK_DLL;????????? je ne vois vraiement pas comment faire
          MY_NOTES_LANCEUR.LANCER_NOTES_FORM
    end;
    En fait pour tout vous dire il s'agit d'un gros programme et j'ai décidé de découper ce programme en dll (une dll par fonctionnalité cela me semble plus claire), donc la zone de travail ptr_work était utilisée par l'ensemble de mes fonctionnalités

    Maintenant je ne fais qu'externaliser chaque fonctionnalité pour en faire une dll et je n'ai rien touché en ce qui concerne la gestion de la zone de working.
    et don dans mon exe je travail avec ptr_work et dans chaque dll (fonctionnalités) je travail aussi avec ptr_work.

    Pensez-vous que je dois modifier la gestion de cette zone de travail (un tableau, un stringList, un pointer que sais-je)

    Cordialement

  7. #7
    Membre chevronné
    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
    Points : 2 158
    Points
    2 158
    Par défaut
    Oui .....
    Je partirais plutot sur une classe TWorkspace qui manipule les données et qui est implementee dans l'exe.

    Ensuite avec le systeme des interfaces, chaques Dlls pourra lire ou ecrire des données dedans.

    Ca fera a mon avis plus propre ...

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    Super, je n'y avait pas penser à la class, c'est la classe


    PS: je laisse ouvert cette disussion au cas où une personne aurais un bonne idée comme la tienne, une fois terminer je cloturerai cette discussion

    encore une fois merci
    Cordialement
    QAYS

  9. #9
    Membre chevronné
    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
    Points : 2 158
    Points
    2 158
    Par défaut
    Je me permet de rajouter que la transmission de classe de Exe a Dll n'ets pas triviale loin de la !

    Donc cela n'est envisageable qu'au travers d'interfaces .....
    Renseigne toi bien sur leur fonctionnement si tu ny est pas habitué

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    Bonsoir

    j'ai crée un class tworkspace et je la passe en parametre et malheureusement j'ai toujours le problème,

    Je suis sur que mon problème à pour origine la passage (interface) de la fonction de ma dll je ne sais vraiement pas comment faire, si vous avez une solution, elle serait la bienvenue

    pour info voila le 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
     
     
    Procedure AFFICHE_NEW_NOTE(ParentApplication: TApplication;
                             ParentMDIFORM:TFORM;
                             ParentDATABASE:My_T_DATABASE;
                             ParentSESSION:MY_T_SESSION_TRANSACTION;
                             PTR_WORK_T:TWORK_CLASS); export;stdcall;
    var
    PTR_WORK_T1:TWORK_CLASS;
    begin
     
          My_DATABASE := ParentDATABASE;
          MY_SESSION_TRANSACTION[1].MY_Transaction := ParentSESSION.MY_Transaction;
     
          PTR_WORK_T1:=PTR_WORK_T;
          PTR_WORK_T1.setACOLCELL('NEDRA');
    ou directement
          PTR_WORK_T.setACOLCELL('NEDRA');
          MY_NOTES_LANCEUR.LANCER_NOTES_FORM
    end;
    si il y a ce code


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          PTR_WORK_T1:=PTR_WORK_T;
          PTR_WORK_T1.setACOLCELL('NEDRA');
    ou directement
          PTR_WORK_T.setACOLCELL('NEDRA');
    j'ai le trap lorsque que je quitte l'exe par contre si il n'y a pas ce code pas de trap


    cordialement
    Kaiss

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    A y est je pense avoir trouve(en tous les cas je n'ai plus le problème)

    mais je ne reussi pas à m'expliquer cette réussite:

    voici le code, si vous avez une explication, je suis preneur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Procedure AFFICHE_NEW_NOTE(ParentApplication: TApplication;
                             ParentMDIFORM:TFORM;
                             ParentDATABASE:My_T_DATABASE;
                             ParentSESSION:MY_T_SESSION_TRANSACTION;
                             ParentWORK:TWORK_CLASS); export;stdcall;
     
    begin
     
          My_DATABASE := ParentDATABASE;
          MY_SESSION_TRANSACTION[1].MY_Transaction := ParentSESSION.MY_Transaction;
          PTR_WORK_T1:=ParentWORK;
          MY_NOTES_LANCEUR.LANCER_NOTES_FORM
    end;
    Où PTR_WORK_T1 est ma zone de travail et elle est utilisé dans le bloc notes et je peux la modifier sans problème et retrouver les modifications dans l'exe après le fermeture de l'écran bloc notes.

    Merci à Clorish pour ces conseils

    Cordialement
    QAYS

  12. #12
    Membre chevronné
    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
    Points : 2 158
    Points
    2 158
    Par défaut
    non ce code n'ets pas bon du tout
    Enfin il marche peut etre dans certains cas mais ce n'ets pas ce qu'il y a de plus "propre" on va dire

    J'ai vu dans ta fonction que tu passe un TApplication, puis au moins un TForm.

    Comme je te l'ai dit, on ne peux pas passer d'objets directement en tant que parametre de fonction. Il faut passer par une interface.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Type 
      TMonInterface = Interface
        Procedure MaProc; StdCall;
      End;
    Ensuite cette interface doit etre implementee dans un objet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Type
      TMonObjetInterfaced = Class(TInterfacedObject, IMonInterface)
      Private
        [...]
      Public
        Procedure MaProc; Stdcall;
      End;
     
    Procedure TMonObjetInterfaced.MaProc;
    Begin
    [...]
    End;
    Ensuite, la fonction de ta Dll doit prendre en compte une interface et non un objet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Proceudre DllExportedProc([...], Intf : IMonInterface, [...]);
    Begin
    Intf.MaProc;
    End;
    Depuis l'exe, on apelle la procedure comme suis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Var Intf : IMonInterface;
     
    Intf := TMonObjetInterfaced.Create;
    DllExportProc([...], Intf, [...]);
    LA liberation d'un objet manipulé en tant qu'interface ne se fait pas par free mais par affectation a Nil :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Var Intf := IMonInterface;
    Intf := TMonObjetInterfaced.Create;
    Intf := Nil;
    Voila pour les bases de la gestion des interfaces.
    Pour plus de details, il est preferable de se pencher un peu plus sur les cours proposé ici ... notement le tres bon chapitre gratuit sur les "plugins" de Paul Toth, dans le livre "Delphi 7 Studio" de chez Eyrolles. La version PDF de ce chapitre se trouve sur le site section cours, ou tutoriels je ne sais plus.

    Ensuite en ce qui te conserne, Je pense qu'il serait bien de creer une classe TWorkspace qui manipule ta zone de memoire "partagee", lui declarer une interface avec des methodes pour la gerer.
    C'est en tant qu'interface que tu va transmettre cet objet a ta dll et que tu pourras y acceder.

    Ensuite, certains objets (comme les tforms) ne sont pas directement ou aisaiement manipulable via les interfaces dans une Dll .... du moins quand on debute.
    Le mieux a faire est de creer une classe speciale, qui implemente l'interface qui qui va "piloter" la classe de base.
    PAr exemple :
    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
     
    Type
      TMonInterfacedForm = Class(TInterfacedObject, IForm);
      Public
        Procedure SetVisible; StdCall;
        Procedure Show : StdCall;
      End;
     
    Procedure TMonInterfacedForm.SetVisible(Value : Boolean);
    Begin
    Form1.Visible := AValue;
    End;
     
    Procedure TMonInterfacedForm.Show;
    begin
    Form1.Show;
    End;
    Je n'ai pas repris le code de l'interface mais je pense que tu sauras le retrouver si tu as bien suivi

    Ca parrait assez complexe a premiere vu, d'ou mon encouragement a aller voir plus loin dans les cours, mais cela ouvre de sacrees portes une vois plus ou moins bien maitrisées.

    Bon courrage pour la suite !

  13. #13
    Membre chevronné
    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
    Points : 2 158
    Points
    2 158
    Par défaut
    Note : Pour le TApplication, il est possible de faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Procedure InitializeApplciation(AppHandle : THandle);
    Begin
    Application.Handle := AppHandle;
    End;
    et dans l'exe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InitializeApllication(Application.Handle);
    Ici le processus est legerement differents car les 2 variable application sont differents mais reagissent sur le meme handle
    On ne tente pas d'acceder a une zone memoire de l'exe via une variable de la dll ... qui est interdit sous peine de violation d'acces (sauf cas tres precis)

    Par contre, pour l'explication en detail, je laisse mes collegues s'en charger
    Je ne maitrise pas trop cet aspect

  14. #14
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    Bonjour,

    Pour tout avoué, je ne suis pas un grand spécialiste des ces notions, je vais donc l'étudier avec soin en tous les cas merci bcp de ces précisions qui me premettrons de travailler plus proprement


    Cordialement
    Qays

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/10/2006, 15h29
  2. DialogBox qui appelle une DialogBox
    Par dede92 dans le forum Windows
    Réponses: 4
    Dernier message: 03/10/2006, 15h24
  3. Page Html qui appel une function
    Par grimsk dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 15/09/2006, 20h01
  4. Connaitre le processus qui appelle une fonction API
    Par RazielReaver dans le forum API, COM et SDKs
    Réponses: 9
    Dernier message: 28/05/2006, 13h56
  5. [PL/SQL] Trigger qui appelle une procédure
    Par alex6891 dans le forum Oracle
    Réponses: 5
    Dernier message: 19/01/2006, 09h01

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