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 :

Aide pour utilisation d'une fonction DLL


Sujet :

Langage Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Par défaut Aide pour utilisation d'une fonction DLL
    Bonjour,

    J'ai une fonction à utiliser pour compresser un fichier dans un format particulier. La seule chose que j'ai c'est une dll avec les entêtes des fonctions C++.

    Voici la fonction C++ que je souhaite utiliser:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned long compress(void* source, void* dest, unsigned long size)
    Dans la mini doc fournie avec, j'ai juste la description de cette fonction:
    - void* source = correspond aux données à compresser
    - void* dest = buffer pour les données compressées
    - unsigned long size = taille des données à compresser
    - la fonction retourne la taille des données une fois compressées

    Donc pour utiliser la dll, j'ai ajouté cette ligne avant l'implémentation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function compress(source : Pointer; dest : Pointer; taille : Longword) : Longword; stdcall; external 'comp.dll';
    Mais le problème ensuite est que je sais pas comment utiliser la fonction Je suis pas très bon lorsqu'il s'agit d'utiliser des pointeurs ou des flux...

    J'ai essayé ceci mais ça ne fonctionne pas, l'application plante avec une erreur "Access Violation at address xxxx"
    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
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      tailleFichierSource : cardinal;
      streamSource : Tfilestream;
      streamDestination : TfileStream;
    begin
    //fichier à compresser
      streamSource := Tfilestream.create('D:\test.dat', fmOpenRead or fmShareExclusive);
    //destination ; le fichier test_c.dat est déja créé mais est vide
      streamDestination := Tfilestream.create('D:\test_c.dat', fmOpenWrite or fmShareDenyWrite);
     
      //récupère la taille du fichier à compresser
      tailleFichierSource := streamSource.size;
     
      try
    	  //appel de la fonction
    	 compress(streamSource,streamDestination,tailleFichierSource);
      finally
    	  //ferme les fichiers
    	  streamDestination.Free;
    	  streamSource.Free;
      end;
    end;
    Si quelqu'un a une idée... car je sais pas quoi faire de plus, je suis bloqué dessus depuis plusieurs heures. Merci d'avance

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    Tu passes un objet Delphi à une fonction C++; c'est normal que ca coince... Tel que tu l'as déclaré, Compress() attends logiquement un pointeur sur une zone mémoire à traiter. Si tu utilisais des TMemoryStream, un truc du genre devrait marcher :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    compress(streamSource.Memory,streamDestination.Memory,streamSource.Size);
    Maintenant, comme tu travailles avec des TFileStreams, tu dois certainement passer par soit des tampons temporaires (lire dans les streams, stocker dans le tampon, compresser le tampon, ajouter le tampon compressé dans le flux cible, recommencer) qui pourraient être pris en charge par des "array of Byte", ou bien transformer ton code pour utiliser des objet qui permettent l'accès au flux d'octets qu'ils gèrent tels les TMemoryStream/

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Par défaut
    Merci. Je suis entrain d'essayer avec un memory stream.
    Pour charger un fichier dans cette stream, j'ai donc juste à utiliser la méthode LoadFromFile() ? Car même avec ça, j'ai toujours une erreur d'access violation A moins que j'ai mal traduit l'entête de ma fonction c++ => delphi?

  4. #4
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    En fait, c'est normal que ca bugge. La DLL va écrire à l'adresse pointée par streamDestination.Memory, et vu que le flux est encore vide à ce stade, va générer une access violation. Le plus logique serait d'utiliser des petits buffers de taille fixe qui seraient écrits au fur et à mesure dans streamDestination. Un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var
       LBufSrc: array [0..BUFSIZE] of Byte;
       LBufDest: array [0..BUFSIZE] of Byte;
       LBytesToWrite: Integer;
     
    ...
     
      ..tant que tu n''as pas traité tout le flux source...
      LBytesToWrite := compress(@LBufSrc[0], @LBufDest[0], BUFSIZE);
      streamDestination.Write(LBufDest[0], LBytesToWrite);
      ... etc.

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Par défaut
    Wow c'est vrai ça, tu as tout à fait raison! Merciiiiiii
    C'est bien à cause du memory stream de destination qui est vide! Est ce qu'on peut lui allouer une taille, un peu comme malloc en C ? Ca pourrait régler le problème Car la j'ai testé en chargeant mon fichier à compresser dans les deux streams et ça a fonctionné, il a bien écrit dedans mon fichier compressé

    Sinon d'après ce qu'on m'avait dit, cette fonction a besoin de tout le contenu du fichier donc impossible de découper le fichier en plusieurs morceaux. Je suis obligé de lui donner toutes les données en une seule fois.

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Par défaut
    Est ce qu'on peut lui allouer une taille, un peu comme malloc en C ? Ca pourrait régler le problème
    Oui : la définition de la propriété Size réalise l'allocation mémoire en appellant SetCapacity :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TMemoryStream.SetCapacity(NewCapacity: Longint);
    begin
      SetPointer(Realloc(NewCapacity), FSize);
      FCapacity := NewCapacity;
    end;
    Donc quelque chose du genre destStream.size := sourceStream.size avant l'appel devrait fonctionner. Ne pas oublier un destStream.Size := resultat de compress() pour "retailler" le flux de destination à la bonne taille...

Discussions similaires

  1. Aide pour écriture d'une fonction
    Par nbrau dans le forum Général Python
    Réponses: 0
    Dernier message: 11/02/2013, 13h40
  2. Aide pour utiliser une DLL C++ dans D7
    Par ESQUIRO dans le forum Langage
    Réponses: 1
    Dernier message: 15/02/2012, 01h28
  3. Aide pour utiliser une fonction dans un "case"
    Par lcoulon dans le forum Débuter
    Réponses: 2
    Dernier message: 15/10/2009, 22h17
  4. Réponses: 8
    Dernier message: 29/06/2006, 15h37
  5. Réponses: 3
    Dernier message: 14/04/2006, 19h36

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