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 :

Avis aux experts Delphi, Mapping DLL C++ et surcharge TList.


Sujet :

Langage Delphi

  1. #1
    Membre éclairé
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Février 2004
    Messages
    644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Février 2004
    Messages : 644
    Points : 785
    Points
    785
    Par défaut Avis aux experts Delphi, Mapping DLL C++ et surcharge TList.
    Bonjour à tous,

    J'explique la chose ;-) Nous avons créés plusieurs applications en Delphi qui se basent toutes sur une DLL (API) écrite en C++ Builder.

    Après un petit audit de nos codes sources, nous avons constatés qu'il y avait un léger soucis avec les TList que nous employons et qui transitaient entre les applications et la DLL. Le fait est que nous pensions qu'un TList.Clear libérait la mémoire, mais ce n'est pas le cas.

    Donc, dans la DLL C++, j'ai commencé à écrire une classe héritant de TList et surchargeant la méthode Clear de base.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template <class T> class TListDs : public TList
    {
        public:
            void __fastcall Clear (void) {
                for (int i = 0; i < Count; ++i) {
                    delete (T*) Items[i];
                }
                TList::Clear ();
            }
    };
    Via ce code, il est bien plus simple de changer toutes nos déclarations de TList dans la DLL par TListDs<TYPE_CLASSE> et ainsi, nous sommes sûr que tout est bien libéré lorsque nous faisons appel au desctructeur de la classe.

    Le problème est dû à l'héritage qui ne semble pas fonctionnel entre du Delphi et du C++.
    Donc, afin de pallier la chose,

    J'ai déclaré dans ma DLL différentes fonctions retournant un pointeur de type TListDs<....>, jusque l'à tout va bien :-)

    Ce qui donne ceci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        TList * EXPORTCALL NewListPerson (void) {
            return new TListDs <TPerson>;
        }
        TList * EXPORTCALL NewListInteger (void) {
            return new TListDs <int>;
        }
        void EXPORTCALL FreeList (TList *pList) {
            delete pList;
        }
    Au niveau du mapping du côté Delphi, voici ce que j'ai fais.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    function NewListInteger: TList; stdcall;
    function NewListPerson: TList; stdcall;
     
    procedure FreeList (vList : TList); stdcall;
    J'ai essayé et cela fonctionne nickel, les variables créées à l'aide de NewListInteger et NewListPerson sont bien de type TList ce qui permet de garder l'interface d'une TList et lorsque je libère via FreeList, la DLL utilise bien la classe Template que j'ai écris. Ce qui dont est le but de base.

    Le problème est que cela ne peut pas aller si on doit modifier toutes les applications rien que pour les TList.

    Si j'ai bien compris une instance d'une TList est créée à l'aide de TList.Create

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var vList : TList = nil;
    begin
      vList := TList.Create;
      vList.Free;
    end;
    Afin de minimiser les changements dans le code Delphi, il n'est pas intéressant de remplacer les TList.Create par des NewListPerson, etc...

    Alors je me suis dis, "essayons de créer une TListDsPerson" qui utiliserait une fonction Create ( et non le constructeur ), afin d'initialiser la TList et de lui retourner un pointeur correspond au bon type de TList; en l'occurence une NewListPerson;


    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
    21
    22
    23
    24
     
    type
      TListDsPerson = class
        private
          Ptr : TList; 
        public
          function Create : TList;
          procedure Clear; 
      end;
     
    implementation
     
    function TListDsPerson.Create : TList;
    begin
      WriteLn ('TListDsPerson.Create');
      self.Ptr := NewListPerson;
      Result := self.Ptr;
    end;
     
    procedure TListDsPerson.Clear;
    begin
      FreeList (self);
      WriteLn('TListDsPerson.Clear');
    end;
    Et maintenant voici le code que j'utilise pour essayer de tester mon système.
    Le problème est que j'arrive à une erreur me disant ceci lors de la compilation.

    [Erreur] LoadDLL.dpr(45): Forme d'appel de méthode autorisée seulement pour les méthodes de classes


    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
    21
     
    var
      vListPerson : TList = nil;
      vPerson : Pointer;
    begin
      try
        vListPerson := TListDsPerson.Create;
        GetList(vListPerson);   
     
        for Cpt := 0 to vListPerson.Count - 1 do
        begin
          vPerson := vListPerson.Items[Cpt];
          WriteLn ('Id : ' + IntToStr (Cpt));
          WriteLn ('FirstName : ' + GetPersonFirstName (vPerson));
          WriteLn ('LastName : ' + GetPersonLastName (vPerson));
        end;
        vListPerson.Clear;
      except
        WriteLn ('Une erreur est survenue...');
      end;
    end.
    Donc ma grande question, est-il possible de réaliser ce que j'essaie, c'est à dire retourner quelque chose lors du Create, afin de tromper Delphi, ce qui me permettrait de limiter les changements au sein du code existant.

    Si oui, comment ;-)

    Sinon, :'(


    Merci,

    Stéphane
    Nul ne peut mieux connaitre la connaissance qu'elle-même.

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    56
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Marne (Champagne Ardenne)

    Informations forums :
    Inscription : Mars 2002
    Messages : 56
    Points : 63
    Points
    63
    Par défaut
    Slt,

    je n'ai pas lu ton post en entier, mais j'ai cru comprendre que tu partage un objet TList entre un programme Delphi et une dll C++ ?

    si c'est bien ca tu va au devant de gros problème, un programme et une DLL ne doivent partager que :
    - des structures
    - des interfaces
    - des types compatibles COM.

    si tu veut définir un objet dans ta DLL C++, il faut que tu crée une interface qui sera partagé par :
    - la DLL
    - le programme

  3. #3
    Membre éclairé
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Février 2004
    Messages
    644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Février 2004
    Messages : 644
    Points : 785
    Points
    785
    Par défaut
    Pour le partage de TList entre Delphi et C++ Builder, ça fait quelques années que cela fonctionne et aucuns problèmes. Il suffit d'employer aussi le ShareMem au niveau de Delphi et d'employer Memmgr.lib de borland.

    Mais cela ne répond pas à ma question :'(
    Nul ne peut mieux connaitre la connaissance qu'elle-même.

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    292
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 292
    Points : 222
    Points
    222
    Par défaut
    si tu te sens à l'aise tu peux t'inspirer de la procédure Create que tu trouves dans l'unité System en assembleur. Pour ce qui est de l'allocation mémoire pas de problème, il te suffit d'appeler ta fonction NewListPerson. ensuite tu fais un peu d'asm pour affecter le bon pointeur à ton Self.

    si par contre, ça ne te dérange pas de passer de TDsListPerson.Create à TDsListPerson.MyCreate, là il n'y a plus de problème, tu fais une fonction statique.

    [Edit]
    Apparement, le compilateur accepte que tu réaffecte le nom de fonction Create à autre chose qu'un constructor.

    ce qu'il te manque dans ta fonction c'est le mot clé class :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    class function Create: TList;
    oublie ce que j'ai écrit au dessus
    [/Edit]

  5. #5
    Membre éclairé
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Février 2004
    Messages
    644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Février 2004
    Messages : 644
    Points : 785
    Points
    785
    Par défaut Merci Bruno75
    Je viens de tester, et effectivement j'ai tout simplement rajouté 'class' devant mon 'Create' et cela fonctionne nickel.

    En plus, Delphi utilisant le pointeur que je lui retourne, cela me permet d'utiliser mon template qui permet de vider la mémoire de tous les items se trouvant dans ma liste.

    En plus, via cela, pas besoin d'écrire un code spécifique pour chaque TList différentes que j'utilise ;-)

    exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var vList : TList;
     
    begin
      vList := TListPerson.Create; [1]
      vList.Free;                  [2]
      vList := nil;                [3]
    end;
    [1] : la fonction Create de TListPerson retourne bien un pointeur provenant d'une TList, mais d'une TList modifiée :-)
    [2] : vList.Free utilise le Free d'une TList, mais de part le fait que j'emplois un template dans ma DLL, celui-ci appelle bien la méthode surchargée du coté de ma DLL et qui emploit un template ;-)
    [3] : c'est pour le fun ;-)

    Stef

    PS : Je suis arrivé à ce que je voulais.

    Merci encore.
    Nul ne peut mieux connaitre la connaissance qu'elle-même.

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 26/11/2008, 13h57
  2. [VBA-E]Avis aux experts, l'ouverture de fichier
    Par Masmeta dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 16/03/2007, 10h16
  3. Réponses: 4
    Dernier message: 03/02/2006, 11h06
  4. Avis aux experts : accéder aux dimensions d'un tableau.
    Par poulpi dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 25/11/2004, 09h09
  5. avis aux experts-Quels sont les logiciels les plus adaptés??
    Par chouchouappc dans le forum Décisions SGBD
    Réponses: 46
    Dernier message: 20/07/2004, 21h26

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