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 :

Passer un TStringList en paramètre dans une DLL


Sujet :

Delphi

  1. #1
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Par défaut Passer un TStringList en paramètre dans une DLL
    Bonjour,

    je souhaites passer à une DLL un objet TStringList. J'ai donc lu avec attention la FAQ qui indique comment passer un objet en paramètre.

    Une question me vient. Si je passe par exemple le contenu de mon TStringList comme ça :
    machaine1#0machaine2#0#0
    et que j'instancie dans dans ma DLL un objet TStringList dans lequel je vais recopier les chaines.
    Dois-je inclure l'unité ShareMem ?

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Par défaut
    Salut
    Citation Envoyé par bubulemaster Voir le message
    Bonjour,

    je souhaites passer à une DLL un objet TStringList. J'ai donc lu avec attention la FAQ qui indique comment passer un objet en paramètre.

    Une question me vient. Si je passe par exemple le contenu de mon TStringList comme ça :
    machaine1#0machaine2#0#0
    et que j'instancie dans dans ma DLL un objet TStringList dans lequel je vais recopier les chaines.
    Dois-je inclure l'unité ShareMem ?

    Merci d'avance
    En fait, si tu passes directement une TStringList, tu passes le pointeur vers cette liste donc ça peut marcher C'est justement en faisant comme tu veux faire que le problème se pose
    Sinon, si tu as BDS2006, il existe une nouvelle unité qui permet de faire ça: SimpleShareMem (incluse dans BDS)
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 843
    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 843
    Par défaut
    Comme le dit Pedro, le passage par pointeur fonctionne SANS Soucis, tient voici ce que je fais ...

    tient, j'envoie le contenu d'un Memo et le nom du fichier pour faire un SaveToFile

    Coté Appli

    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
    procedure TFrmTestDivers.WriteStringList(const FileName: string; const Strings: TStrings);
    var
      HandleDLL: HMODULE;
      _WriteStringList: procedure(const FileName: string; const Strings: TStrings); stdcall;
    begin
      HandleDLL := LoadLibrary('DLLTest.dll');
     
      if HandleDLL > 0 then
      begin
        try
          @_WriteStringList := GetProcAddress(HandleDLL, 'WriteStringList');
          if Assigned(@_WriteStringList) then
            _WriteStringList(FileName, Strings);
        finally
          FreeLibrary(HandleDLL);
        end;
      end;
    end;
    coté DLL

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure WriteStringList(const FileName: string; const Strings: TStrings); stdcall;
    begin
      if Assigned(Strings) then
        Strings.SaveToFile(FileName);
    end;
    Tant que l'on ne modifie pas les chaines de Strings, cela ne pose aucun problème ... tu peux même echanger des forms, font juste encapsuler au possible toute manipulation de la Form ...

    tu peux aussi le faire comme cela, envoyant comme le disait le Text ...

    Coté Appli

    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
    procedure TFrmTestDivers.SetDLLFormMemo(const Form: TForm; const Lines: string);
    var
      _SetDLLFormMemo: procedure(const Form: TForm; const Lines: string); stdcall;
    begin
      if Form.Tag > 0 then
      begin
        @_SetDLLFormMemo := GetProcAddress(Form.Tag, 'SetDLLFormMemo');
        if Assigned(@_SetDLLFormMemo) then
        begin
          try
            _SetDLLFormMemo(Form, Lines);
          except
            on E: Exception do ShowMessage(E.Message);
          end;
        end;
      end;
    end;
    coté DLL

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure SetDLLFormMemo(const Form: TForm; const Lines: string); stdcall;
    begin
      if Form is TFrmDLL then
        TFrmDLL(Form).MemoDLL.Lines.Text := Lines;
    end;
    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

  4. #4
    Expert confirmé

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure SetDLLFormMemo(const Form: TForm; const Lines: string); stdcall;
    begin
      if Form is TFrmDLL then
        TFrmDLL(Form).MemoDLL.Lines.Text := Lines;
    end;
    Le is ne passera pas. Il sera toujours considéré comme False. Les DLL ne partagent pas les RTTI avec l'application.

    Mais le premier exemple fonctionne.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de [URL="https://www.scala-js.org/"]Scala.js[/URL], le compilateur de Scala vers JavaScript, et directeur technique du [URL="https://scala.epfl.ch/"]Scala Center[/URL] à l'EPFL.
    Découvrez [URL="https://sjrd.developpez.com/"]Mes tutoriels[/URL].

  5. #5
    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
    Outch ... ya des choses qui me font quand meme bien dresser els Zoreil

    Passer des classes, des objets, et des pointeurs vers une Dll ....

    Pour faire propre, l'ideal est la creation de classe interfacees.
    Une classe dans la Dll qui implemente une Interface via laquelle on va transmettre une a une les elements de la Liste est quand meme la meilleur solution.

    Une solution plus simple serait de transmettre via un parametre PChar la property "Text" des TStringList ... parametre qui sera reaffecté dans un TStringList cree dans la Dll via la meme property Text.

    Tant que l'on reste dans le domaine Delphi/Delphi pour creer Exe//dll ca passe avec sharemem, ... mais des que l'on cherche a aller plus loin ca va vite casser. D'ailleur c'est pas non plus le role des Dll de faire ce genre de choses.
    A la limite, passer par des Packages est mieux sur ce point la.

    Au moins on assure la la restriction Delphi/Delphi et en plus on beneficie des infos RTTI.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 843
    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 843
    Par défaut
    Citation Envoyé par sjrd Voir le message
    Le is ne passera pas. Il sera toujours considéré comme False. Les DLL ne partagent pas les RTTI avec l'application.

    Mais le premier exemple fonctionne.
    Sauf si la Form est instancié du côté DLL ^_^, ce qui est le cas dans mon programme ... tout le monde s'ait que l'on instancie d'un côté, que l'on manipule du même coté, et que l'on échange juste des pointeurs pour savoir sur quoi agir entre Appli et DLL ...

    Ensuite, si Exe et DLL sont construits avec paquet d'execution, il n'y pas plus aucun problème les classes sont communes au deux, tient voir ici, on en parlait déjà, ou encore là, où j'ai bidouillé le partage des classes !
    Je ne retrouve pas, j'avais expliqué grossièrement, pourquoi on partagerais pas les classes, une histoire de compilation et d'identifiant calculé à ce moment (l'emplacement mémoire aussi, j'ai fouillé dans TypInfo, c'est des grands malades, quand même chez Borland)

    Citation Envoyé par Clorish Voir le message
    Outch ... ya des choses qui me font quand meme bien dresser els Zoreil

    Passer des classes, des objets, et des pointeurs vers une Dll ....

    Pour faire propre, l'ideal est la creation de classe interfacees.
    Je sais bien mais quand tu n'as pas le temps ou que tu n'y arrive pas bien avec ces interfaces (je n'en ai pas refait depuis une lib trop propriétaire, faut que je lises le Tuto de Laurent Dardenne), quand tu pense que dans une des société où je suis passé (2 ans), ils avaient une lib commune partagé par une 50aine de développeur, et que pour passer les Forms et Panel, ils passait via un integer qui n'était un cast de la référence, alors que tout était développé sous la forme d'Activex (plus d'un milliers de dll, deux fois plus d'objets) et que les mécanismes de base était fait par des bidouilles, aulieu d'un IStandardxxxForm ... par exemple exploité jusqu'au bout (il en existait une partiellement, et la moitié des fonctions dans cette Interface, donc on utilisait l'ancienne lib en pointeur)

    Sinon, pour les Chaines, effectivement, le PChar a l'avantage d'être standard ... contrairement à la chaine delphi qui est très particulière mais en const, cela ne pose pas de problème, on peut même le récupéré en C (une chaine delphi contient toujours un #0 à la fin en plus (2 pour un Wide), et sinon il y a la longueur en p-4)

    En tous cas, le nombre de fois que je bidouille un truc pour envoyer des structures entre deux exe par pointeur avec un message WM_COPYDATA, que l'on doit considérer comme lecture seule, ... tient windows indique la même limite que les string ... perso, je préfère me débrouiller sans BordelMM.dll soit en respectant les types C (on a l'habitude avec l'API Windows), soit par bidouille (même si j'évite, mais avec les Forms hum ...)
    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
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Par défaut
    Et si je passe un pointer de TStrings (@MaTString) est-ce je m'affranchis des contrainte de ShareMem ?

  8. #8
    Expert confirmé

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Par défaut
    Non, certainement pas.

    On te l'a déjà dit. Le meilleur moyen de passer ta liste est de passer via PChar le contenu de sa propriété Text, puis de refaire la conversion inverse côté DLL.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de [URL="https://www.scala-js.org/"]Scala.js[/URL], le compilateur de Scala vers JavaScript, et directeur technique du [URL="https://scala.epfl.ch/"]Scala Center[/URL] à l'EPFL.
    Découvrez [URL="https://sjrd.developpez.com/"]Mes tutoriels[/URL].

  9. #9
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 843
    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 843
    Par défaut
    Comme te l'a dit Pedro, c'est possible dans des cas très limité, il vaut mieux déployer la DLL Borland et ShareMem ou FastShareMem, ...

    Si la TStrings n'est pas modifié dans la DLL, c'est possible mais absolument pas recommandé, et il vaut mieux compiler l'Exe et la DLL avec les paquets d'execution pour le partage des informations de classes (RTTI), mais bien sur, il ne fait faire AUCUNE modification, cela doit être que de la lecture seule, pour des insertions, tri (sort), effacement, ... tu dois le passer via des PChar

    EXE
    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
    procedure TFrmTestDivers.SendStringList(const Strings: TStrings);
    var
      HandleDLL: HMODULE;
      _SendStringList: procedure(AText: PChar); stdcall;
    begin
      HandleDLL := LoadLibrary('DLLTest.dll');
     
      if HandleDLL > 0 then
      begin
        try
          @_SendStringList:= GetProcAddress(HandleDLL, 'SendStringList');
          if Assigned(@_WriteStringList) then
            _SendStringList(PChar(Strings.Text));
        finally
          FreeLibrary(HandleDLL);
        end;
      end;
    end;
    DLL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure SendStringList(AText: PChar); stdcall;
    var
      SL: TStrings;
    begin
      SL := TStringList.Create();
      try
        SL.Text := AText;
        ... Calcul
      finally
        SL.Free();
      end;
    end;
    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

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/07/2007, 11h31
  2. Réponses: 2
    Dernier message: 11/10/2006, 14h37
  3. Réponses: 1
    Dernier message: 21/03/2006, 15h29
  4. Paramètre Pchar dans une DLL
    Par Writer dans le forum Langage
    Réponses: 4
    Dernier message: 25/08/2005, 02h33

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