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 :

Exécutable et DLL dans deux versions Delphi


Sujet :

Langage Delphi

  1. #1
    Membre régulier
    Exécutable et DLL dans deux versions Delphi
    • Je dispose d'un exécutable compilé avec Delphi XE7 PRO (je n'ai pas les sources à ma disposition)
    • Je dispose d'une DLL également compilée avec Delphi XE7 PRO (dont j'ai les sources à disposition)


    Le processus, qui fonctionne parfaitement dans ce cas de figure, est en gros :


    1. L'exécutable est lancé et charge automatiquement la DLL
    2. L'exécutable affiche une IHM
    3. L'appui sur un bouton de l'IHM demande à la DLL :
      1. de créer une fiche
      2. de l'afficher de façon modale.





    La création et l'affichage de la fiche:

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    _maFiche:=TMaFiche.create(NIL);
    _maFiche.showModal;



    Maintenant, je compile le source de la DLL mais en utilisant Delphi 10.3.3 Community Edition.

    Le processus devient :

    1. L'exécutable est lancé et charge automatiquement la DLL
    2. L'exécutable affiche une IHM
    3. L'appui sur un bouton de l'IHM demande à la DLL :
      1. de créer une fiche
      2. de l'afficher de façon modale. --> déclenchement d'une exception



    En pistant dans le code source DELPHI il s'avère que l'exception est déclenchée dans la méthode :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    function TCustomForm.ShowModal: Integer;

    sur l'instruction
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Application.HandleMessage;


    N.B. avec le code ci-dessous il n'y a pas de déclenchement d'exception :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    _maFiche:=TMaFiche.create(NIL);
    _maFiche.show;


    Mes questions/demandes :
    • la création de fiches dans une DLL compilée avec une version différente de Delphi de celle utilisée pour compiler l'exécutable est elle absolument à proscrire, faut-il impérativement passer par des packages ?
    • est-il possible de développer un showmodal like qui ne produirait pas cette exception ?

  2. #2
    Expert éminent sénior
    est-ce qu'il y a passage de classes objets entre l'exe et la DLL ?

    ce qui peut fonctionner avec ShareMem pour des projets compilés avec la même version de Delphi, mais ne fonctionnera pas pour des projets avec des versions différents (sauf coup de bol) car pour peu que la classe ou un de ses ancêtre a été modifié depuis, le code de la DLL utilise à tord le nouveau code sur un ancien objet.

    j'ai vu un jour un projet Delphi 5 et une DLL 2005 qui cohabitaient en partageant un TStringList...mais sans le faire exprès le développeur n'utilisait la liste qu'en en invoquant des méthodes virtuelles, du coup c'est la méthode de l'exe qui était invoqué par la DLL ce qui est le principe même d'une Interface
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre régulier
    Non aucun objet n'est échangé entre l'EXE et la DLL seulement des strings
    J'utilise l'unité simpleShareMem pour l'EXE et la DLL

  4. #4
    Expert éminent sénior
    quel est le message de l'exception ?
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Membre régulier
    Le message affiché est (Ogre.exe est l'exécutable) :

    Violation d'accès à l'adresse 00000267 dans le module 'Ogre.exe'. Lecture de l'adresse 00000267.


    Si je fais

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    _maFiche.show


    Qui se passe bien, alors toute tentative d'afficher une sous-fiche en "showModal" produit une exception similaire

  6. #6
    Membre régulier
    Pour répondre plus exactement à la demande de Paul, j'ai bien un passage d'objet depuis l'exécutable vers la DLL,il s'agit de l'objet APPLICATION.

    Dans l'initialisation de la classe de base (celle dont dérivent toutes les classes dans ma DLL) j'ai le code suivant :


    Code pascal :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TclasseNumero1.initialise;
    begin
      if (Application = nil) then
        if (_securite <> nil) and (_securite.MainAppli <> nil) then
          attacheDll(_securite.MainAppli);
    end;


    "_securite" est une interface transmise par l'exécutable à la DLL et qui permet de récupérer l'objet APPLICATION de cet exécutable.

    La procédure "attacheDLL" est définie dans une unité : "passeAppliToDLL" dont le code est :

    Code pascal :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
    unit passeAppliToDLL;
     
    interface
     
    procedure ATTACHE_DLL(MainApp: TObject);
    procedure DETACHE_DLL;
    function getDllApp: TObject;
     
    implementation
     
    uses Forms;
     
    var
      DllApp: TApplication;
     
     
    function getDllApp: TObject;
    begin
      if Assigned(DllApp) then
        result := DllApp
      else
        result := Application;
    end;
     
    procedure ATTACHE_DLL(MainApp: TObject);
    begin
      if (MainApp <> nil) and not Assigned(DllApp) then
      begin
        DllApp := Application;
        Application := TApplication(MainApp);
      end;
    end;
     
    procedure DETACHE_DLL;
    begin
      if Assigned(DllApp) then
      begin
     
        Application := DllApp;
        DllApp := nil;
      end;
    end;
     
    initialization
      DllApp := nil;
     
    finalization
      DETACHE_DLL;
     
    end.


    La redécouverte de ce code (que j'avais un peu oublié) m'a permis de résoudre mon problème avec le "showModal" de la façon suivante :

    Code pascal :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure TmaFiche.montrer;
    var app:TObject;
    Begin
           {$IFDEF VER330}
              app:=getDllApp;
              DETACHE_DLL;
           {$ENDIF}
     
             showModal;
     
           {$IFDEF VER330}
             attache_DLL(app)
           {$ENDIF}
    End;


    Qu'en pensez-vous ?