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 :

Est-il possible de faire passer une exception d'une DLL à son exe hôte ?


Sujet :

Langage Delphi

  1. #1
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut Est-il possible de faire passer une exception d'une DLL à son exe hôte ?
    Est-il possible de faire passer une exception d'une DLL à son exe hôte ?

    Si dans une fonction de la DLL, je fais un raise Exception, l'exe hôte peut-il récupérer l'exception avec un try ... except autour de l'appel de la fonction ?
    On m'affirme que oui, mais quand je teste, j'ai juste une violation d'accès côté exe, et pas le message de l'exception.


    Y a t'il une façon de faire particulière, ou ce n'est pas possible ?
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Comme argument de la fonction : TryMyFunction(paramètres ; ExceptionHasOccured: Boolean; ExceptionRaised: Exception); ? mais ça ne déclenche pas d'exception...
    En déclenchant une CallBack OnExceptionDo ? Mais il n'y aura pas d'exception dans le code qui entoure l'appel à la fonction...
    Grâce à une fonction anonyme ? Mais je ne sais pas où s'interceptera l'exception qu'elle devrait propager...
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Comme argument de la fonction : TryMyFunction(paramètres ; ExceptionHasOccured: Boolean; ExceptionRaised: Exception); ? mais ça ne déclenche pas d'exception...
    En déclenchant une CallBack OnExceptionDo ? Mais il n'y aura pas d'exception dans le code qui entoure l'appel à la fonction...
    Grâce à une fonction anonyme ? Mais je ne sais pas où s'interceptera l'exception qu'elle devrait propager...
    Effectivement, pour contourner le problème, j'avais suggéré de passer par un paramètre (bonne idée aussi, la procédure OnExceptionDo ).
    Mais, on m'affirme que c'est plus propre par une exception, et que ça marche très bien (à la gestion de l'unicode près, pour le libellé de l'erreur).

    Précision que j'avais oublié : ça doit être compatible Delphi 2007.

    Si personne n'a d'idée, je vais rester sur mon idée de paramètre ...
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Une compilation de l'EXE et de la DLL avec des packages BPL, le gestionnaire mémoire partagée permet cela.
    Delphi 2007, vérifier l'utilisation de ShareMem+borlndmm.dll, SimpleShareMem ou FastShareMem,
    Depuis que FastMM est inclu par défaut (2009 ?), il y a des précautions à prendre avec les anciens Delphi qui sont plus simples aujourd'hui
    un raise dans la DLL va instancier une classe d'Exception contenu dans le BPL (même ses propres classes d'exception, faut les déporter en DPK et produire un BPL)
    L'exe va recevoir l'Exception et comme il la connait via le BPL, il va la gérer tout à fait naturellement.
    La mémoire étant partagée via borlndmm.dll pour 'instanciation des Classes et des Chaines, ainsi que leur libération

    Si le mode BPL n'est pas souhaité, mieux vaut rester dans du standard WinAPI
    Car même ne passant l'Exception en paramètre, la table des adresses des classes étant différentes, il peut y avoir des difficultés à ce que l'EXE reconnaissent une Exception de la DLL même si c'est le même type, il est adressé différement dans les deux, tout le monde qui travaillent avec des DLL/EXE + TForm connaissent le message Impossible d'affecter TFont à TFont, c'est le même phénomène

    En WinAPI, c'est un code d'erreur qui est retourné, un BOOL + GetLastError, un LONG contenant directement un code d'erreur ou un HRESULT avec une valeur fournie par MS
    Il faut juste faire une unité MaDLLConsts qui est partagé entre Exe et DLL pour lister les codes d'erreur et une table d'association
    Il est aussi possible d'inlcure un GetLastError et FormatErrorMessage spécifique à la DLL pour éviter le partage de cette unité.


    Citation Envoyé par Lung Voir le message
    Mais, on m'affirme que c'est plus propre par une exception
    Je serais curieux de savoir les propos exact car il n'y a rien de plus moche que d'échanger des objets lorsque l'on ne fonctionne avec les paquets d’exécution BPL partagés par EXE/DLL.

    Sans les BPL et le gestionnaire de mémoire partagé, il est plus élégant d'utiliser des interfaces et un HRESULT pour la gestion d'erreur
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    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 445
    Points
    28 445
    Par défaut
    intuitivement je dirais que ça doit fonctionner...quand on fait un appel à une fonction Windows qui plante, on a bien la possibilité de capturer l'exception...par contre elle ne sera pas typée, c'est une exception externe.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Pour développer les propos de Paul TOTH, cela correspond à EExternalException pour une liste précise d'Exceptions natives du Système d'Exploitation, cela remonte grâce aux mécanisme d'exception de l'OS sur lesquels Delphi se branchent pour les capturer et que l'on puisse les traiter, c'est un cas très particulier, j'ignore même si l'on peut soit même déclencher ce type d'exception

    Nom : ExceptionNativeSE.jpg
Affichages : 348
Taille : 84,9 Ko
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    car il n'y a rien de plus moche que d'échanger des objets lorsque l'on ne fonctionne avec les paquets d’exécution BPL partagés par EXE/DLL.
    Pourquoi ?



    Sinon, on a testé avec une DLL et un exe tous les 2 en D10.3, et on peut capturer une exception.
    Mais, comme on doit rester compatible avec les exe en D2007, on va partir sur un objet en retour de fonction, qui contiendra tout : les paramètres à retourner, plus un code de retour (erreur ou pas), plus une chaine d'erreur (si erreur).

    pour votre aide (je me note les différentes idées, pour d'autres développements).
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par Lung Voir le message
    Pourquoi ?
    Parce que l'objet compilé dans l'EXE n'est pas le même que l'objet compilé dans la DLL, tu peux avoir des options de compilation différentes qui pourraient les rendre incompatible.
    Le Code dans l'EXE se situe à une adresse mémoire précise et celui dans la DLL à une autre, toutes les RTTI sont adressées ailleurs voir mêmes différentes puisque 10.3 possède de nouvelles RTTI.

    Et vouloir partager des objets entre D10.3 et D2007, rien ne garanti qu'un ancêtre de l'objet n'ait pas évolué, rien que le TObject (n'est-il pas différent en InstanceSize entre les deux ?)
    Et je n'évoque même par le chaines string Unicode dans l'un et Ansi dans l'ancien, le StrRec préfixant la chaine a changé, la taille du Char a changé
    Le gestionnaire de mémoire par défaut est différent sauf si vous avez choisi FastMM pour les deux par exemple

    Rien qu'une seule de ces raisons fait que l'on ne devrait pas de partir sur un échange d'objet, alors cumulées

    Le plus propre c'est des Interfaces et des BSTR (WideString)
    Les interfaces sont libérées du côté de celui qui les instancient (très important quand le gestionnaire de mémoire n'est pas partagé)
    Les chaines WideString sont alloués en mémoire OLE\COM (c'est plus compliqué que ça mais simplifions) ainsi la DLL peut retourner une chaine, l'EXE peut la libérer sans problème.

    Sinon, un record et du PAnsiChar comme pour l'API Windows
    une unité type header partage entre EXE et DLL serait préférable en incluant des options comme {$ALIGN ON} pour garantir que le record soit compatible
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Et vouloir partager des objets entre D10.3 et D2007, rien ne garanti qu'un ancêtre de l'objet n'ait pas évolué, rien que le TObject (n'est-il pas différent en InstanceSize entre les deux ?)
    Si je comprend bien, c'est pour cette raison que la classe Exception n'est pas la même entre ces différents Delphi.

    Citation Envoyé par ShaiLeTroll Voir le message
    Et je n'évoque même par le chaines string Unicode dans l'un et Ansi dans l'ancien, le StrRec préfixant la chaine a changé, la taille du Char a changé
    Pour les chaines, j'avais fait des tests et j'avais vu que seul le PAnsiChar permettait de passer des chaines entre 2007 et D10.3.

    Citation Envoyé par ShaiLeTroll Voir le message
    Le plus propre c'est des Interfaces et des BSTR (WideString)
    Les interfaces sont libérées du côté de celui qui les instancient (très important quand le gestionnaire de mémoire n'est pas partagé)
    Là, j'aimerais bien plus d'explications.
    Je n'ai jamais compris à quoi pouvait servir les interfaces, quand les classes abstraites existent.

    Citation Envoyé par ShaiLeTroll Voir le message
    Sinon, un record et du PAnsiChar comme pour l'API Windows
    C'est exactement ce que j'ai proposé : un simple record. Mais la majorité à préféré un objet, "parce que c'est pareil en mieux".
    Sauf qu'un objet, faut penser à le libérer.

    Citation Envoyé par ShaiLeTroll Voir le message
    une unité type header partagée entre EXE et DLL serait préférable en incluant des options comme {$ALIGN ON} pour garantir que le record soit compatible
    Qu'est ce que tu appelles "type header" ?
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  10. #10
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    Citation Envoyé par ShaiLeTroll
    Le plus propre c'est des Interfaces et des BSTR (WideString)
    Les interfaces sont libérées du côté de celui qui les instancient (très important quand le gestionnaire de mémoire n'est pas partagé)
    Là, j'aimerais bien plus d'explications.
    Je n'ai jamais compris à quoi pouvait servir les interfaces, quand les classes abstraites existent.
    Les interfaces définissent un contrat.
    En gros, elle définissent le "quoi" et laissent le "comment" aux classes qui vont l'implémenter.
    Si une classe implémente une interface, elle doit obligatoirement fournir une implémentation pour chacune des méthodes du contrat.
    Tu verras donc dès la compilation si tu as un problème car ça ne compilera pas.

    Les classes abstraites définissent un contrat et une partie de l'implémentation.
    Lorsqu'une classe hérite d'une classe abstraite, rien ne t'oblige à redéfinir une méthode.
    Tu as potentiellement un avertissement en compilation mais ça compile.
    Si jamais tu as oublié de redéfinir une méthode déclarée virtual abstract dans l'ancêtre et que tu l'utilise tu ne verras l'erreur qu'au moment de l'exécution.

    Tu ne peux pas hériter de plusieurs classes abstraites mais tu peut implémenter plusieurs interface.
    Les interfaces sont automatiquement libérée lorsqu'elle ne sont plus utilisées.

  11. #11
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par popo Voir le message
    Les interfaces sont automatiquement libérée lorsqu'elle ne sont plus utilisées.
    Ça veut dire qu'un objet dont la classe hérite d'une interface, va se libérer tout seul ?
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Uniquement si la déclaration et instanciation est comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var
      MonIntf: IBidule; // Ici c'est une variable de type interface
    begin
      MonIntf := GetBiduleFromDLL(); // ici MonIntf._AddRef est appelé, cela incrémente le compteur de référence
      MonIntf.Truc();
    end; // ici MonIntf.Release est appelé, cela décrémente le compteur de référence, si Zero = Libération
    Entre la DLL et EXE, il y aura un fichier PAS décrivant les Interfaces, c'est une "unité type header"
    Mais seule la DLL contient le PAS fournissant l'implémentation

    une "unité type header" c'est comme Winapi.Windows.pas, c'est juste des déclarations de types, de constantes, de fonctions externes ...
    Je parlais header comme en C++, le .h ou hpp, lorsque l'on programme en Windows, c'est la base comme Windows.h, winbase.h, winuser.h ...

    Avec un ActiveX, l'importateur de Delphi génère un Wrapper TLB que l'on peut aussi considéré comme une "unité type header" cela ne déclare que les types et quelques assistants pour l'instanciation/libération


    Pour les interfaces, vous avez un début de réponse dans la FAQ - Comment partager un objet entre un exécutable (.exe) et une DLL? dans l'approche "Deuxième méthode : Utilisation des interfaces" pour éviter 'BORLNDMM.DLL' surnommé BordelMM


    C'est exactement ce que j'ai proposé : un simple record. Mais la majorité à préféré un objet, "parce que c'est pareil en mieux".
    C'est mieux dans un contexte interne d'un module
    Mais les contraintes techniques remettent en cause les préjugés.

    Il est évident qu'une DLL exposant des Interfaces (ou à la rigueur un ActiveX) aura donc la préférence.

    Voir Affecter une procédure à un évènement dans une dll

    Et l'excellent : Les interfaces d'objet sous Delphi
    Je me suis éclaté à faire des couches d'abstraction de périphérique à coup de DLL et d'interface pour que dans le programme principal,
    tout soit le plus simple que possible alors que techniquement chaque périphérique avait son propre protocole
    D'ailleurs dans le programme principal, ce n'était pas des interfaces qui étaient manipulé des classes d'encapsulation plus simple à comprendre.


    Si les interfaces te font trop peur au début
    Tu fais ta DLL, tu l'exposes en style WinAPI avec du record et du PAnsiChar et tu fournis à tes collègues une unité Wrapper qui fourni des classes encapsulant tout le bazar

    Et tu pourras changer ta DLL, changer le style WinAPI en Interface sans que personne n'y voit quelque chose puisque qu'eux ne voit que les classes Wrapper (~Adapter/Proxy) qui n'ont pas changé.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  13. #13
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Bon, j'ai testé en remplaçant les classes par des records dans les paramètres.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      TSearchCriterias = record
          SearchType        : PAnsiChar;
          BrandSource       : PAnsiChar;
          BrandExternalId   : PAnsiChar;
          BrandName         : PAnsiChar;
          BrandRef          : PAnsiChar;
          BarcodeValue      : PAnsiChar;
          ProductSource     : PAnsiChar;
          ProductExternalId : PAnsiChar;
      end;
    Tout à l'air de fonctionner, sauf que à la fermeture de l'exe hôte, le processus reste actif.
    Et si je fais le FreeLibrary, l'exe reste coincé dessus.

    Donc, avec des classes ou des enregistrements, le résultat semble le même.


    J'ai testé également de ne faire que le LoadLibrary et les GetProcAddress, et quitter juste après. Même chose : le processus reste actif. Et si j'utilise le FreeLibrary, ça fige dessus.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  14. #14
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    J'ai tenté de charger ma DLL en statique (pour voir).

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
         function SearchSaveAndReportProducts(AsearchCriterias: TSearchCriterias; AMonoColor: Boolean): Integer;   stdcall;   external 'LibHubSearchProduct.dll';
    Quand je lance l'exe, il démarre et se referme aussitôt.
    J'ai supposé que s'était parce qu'il ne trouvait pas la DLL. J'ai mis le chemin complet dans le external (juste pour tester): même chose.
    J'ai essayé de l'enregistrer avec regsvr32. Mais il me retourne une erreur, comme si ma DLL n'en était pas une :
    Le module «*C:\Users\DEVXE\Desktop\Test\Win32\Debug\LibHubSearchProduct.dll*» a été chargé, mais le point d’entrée DllRegisterServer est introuvable.

    Vérifiez que «*C:\Users\DEVXE\Desktop\Test\Win32\Debug\LibHubSearchProduct.dll*» est un fichier DLL ou OCX valide, puis réessayez.
    C'est quoi ce point d'entrée DllRegisterServer ?

    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  15. #15
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par Lung Voir le message
    Tout à l'air de fonctionner, sauf que à la fermeture de l'exe hôte, le processus reste actif.
    Et si je fais le FreeLibrary, l'exe reste coincé dessus.
    J'ai testé de faire un nouveau projet (D2007) et une nouvelle DLL (D10.3) ne faisant presque rien (que des choses simples, comme retourner un entier en dur, ou le contenu d'une propriété d'un objet).
    Et là, tout marche parfaitement : les appels, les valeurs qui transitent, le FreeLibrary, et la fermeture complète de l'exe.

    Il doit donc y avoir quelque chose qui coince dans la vraie DLL.
    Je creuse ...
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 128
    Points
    13 128
    Par défaut
    Citation Envoyé par Lung Voir le message
    Tout à l'air de fonctionner, sauf que à la fermeture de l'exe hôte, le processus reste actif.
    Et si je fais le FreeLibrary, l'exe reste coincé dessus.
    C'est assez typique d'une allocation faite dans la dll et d'une libération ordonnée depuis l'exe (ou inversement).

    Citation Envoyé par Lung Voir le message
    J'ai tenté de charger ma DLL en statique (pour voir).
    ...
    Quand je lance l'exe, il démarre et se referme aussitôt.
    Il y a une erreur dans l'export.

    Les liaisons sont créées très tôt au lancement du programme, avant le démarrage du gestionnaire d'exception.

    Jette un œil à l'observateur d'événements. Il est probable qu'une erreur soit reportée.
    Si c'est 0xC0000005 (violation d'accès), contrôle Fault Offset.
    Si à 0 (pointeur nil), la fonction n'est pas exportée. Soit il manque l'export dans ton code, soit tu travailles sur la mauvaise dll qui n'en déclare pas.
    Si différent de 0, le prototype de la fonction n'est pas correct. C'est en général ce qui se passe si on utilise la mauvaise version d'une dll tiers.

    Citation Envoyé par Lung Voir le message
    J'ai essayé de l'enregistrer avec regsvr32. Mais il me retourne une erreur, comme si ma DLL n'en était pas une
    Appeler regsvr32 n'a aucun intérêt à moins que ta dll intègre un serveur COM.


    Commence par passer la structure par pointeur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    PSearchCriterias = ^TSearchCriterias;
    TSearchCriterias = record
    end;
    Si pour une raison quelconque l'allocation doit se faire côté dll et la libération côté exe, passe par VirtualAlloc, VirtualFree.

  17. #17
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    C'est assez typique d'une allocation faite dans la dll et d'une libération ordonnée depuis l'exe (ou inversement).
    Rien que faire le LoadLibrary sans rien de plus, et il y a déjà le pb.

    Citation Envoyé par Andnotor Voir le message
    Il y a une erreur dans l'export.
    De quel genre ?
    Si les appels de procédure fonctionnement dynamiquement, c'est que la liste des procédures dans Exports est juste, non ?

    Citation Envoyé par Andnotor Voir le message
    Jette un œil à l'observateur d'événements. Il est probable qu'une erreur soit reportée.
    Dans quel noeud ?
    Il y en a des quantités ?

    Sinon, j'ai beau essayer de tester tout et n'importe quoi pour stabiliser cette DLL, mais je n'arrive à rien.
    A un moment, j'ai cru que c'était la faute des PAnsiChar. Pour certains, faire un GetMem / FreeMem, ça allait mieux. J'ai fait pareil sur d'autres : violation d'accès.
    Pas moyen de trouver ce qui peut poser pb, ou être mal fait, ...

    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 128
    Points
    13 128
    Par défaut
    Citation Envoyé par Lung Voir le message
    Rien que faire le LoadLibrary sans rien de plus, et il y a déjà le pb.
    Est-ce que tu as redéfini DllEntryPoint ?
    Fais-tu quelque chose au Dll_Process_Attach qui n'est pas défait au Dll_Process_Detach ?

    Citation Envoyé par Lung Voir le message
    Si les appels de procédure fonctionnement dynamiquement, c'est que la liste des procédures dans Exports est juste, non ?
    Logiquement oui mais est-ce que le prototype en statique (côté exe) est correct ?
    Un test avec MadExcept pourrait te donner quelques indications supplémentaires.

    Citation Envoyé par Lung Voir le message
    Dans quel noeud ?
    Journaux Windows -> Application. Fais une recherche sur le nom de ton exe.

    Citation Envoyé par Lung Voir le message
    Pour certains, faire un GetMem / FreeMem, ça allait mieux
    En tout cas pas ou à moins ,comme ça a déjà été dit, d'utiliser un gestionnaire de mémoire partagée.
    VirtualAlloc/VirtualFree (ou HeapAlloc/HeapFree pour autant qu'ils utilisent le même tas)

Discussions similaires

  1. Réponses: 1
    Dernier message: 18/06/2015, 09h38
  2. Faire passer une variable à un CSS, est-ce possible?
    Par miltonis dans le forum Mise en page CSS
    Réponses: 9
    Dernier message: 04/10/2006, 16h05
  3. [C#] Est-il possible de faire une référence sans recopie ?
    Par AiSpirit dans le forum EDI/Outils
    Réponses: 8
    Dernier message: 17/07/2006, 09h56
  4. Réponses: 7
    Dernier message: 09/05/2006, 11h30
  5. Est il possible de faire une fusion
    Par boy569 dans le forum Composants VCL
    Réponses: 3
    Dernier message: 07/02/2006, 13h58

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