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

  1. #1
    Membre actif

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Points : 208
    Points
    208
    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 expérimenté

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    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/
    "It's more fun to compute !"

  3. #3
    Membre actif

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Points : 208
    Points
    208
    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 expérimenté

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    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.
    "It's more fun to compute !"

  5. #5
    Membre actif

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Points : 208
    Points
    208
    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 expérimenté

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    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...
    "It's more fun to compute !"

  7. #7
    Membre actif

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Points : 208
    Points
    208
    Par défaut
    Bravo, ça fonctionne
    Problème résolu grace à toi, encore merci, j'y serai pas arrivé tout seul

  8. #8
    Membre actif

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Points : 208
    Points
    208
    Par défaut
    Je remonte ce sujet car j'ai un autre problème et ça concerne toujours cette librairie.

    La compression/décompression fonctionne toujours, jusque la plus de soucis. Par contre la compression ne fonctionne pas si je l'utilise dans un thread (pour ne pas figer l'application).

    Lors de l'appel de la méthode de compression au sein de mon thread, il ne se passe rien et le thread se termine immédiatement sans même exécuter le code qui est censé s'exécuter après la compression. Par contre si j'appelle cette méthode en dehors du thread, aucun soucis ça marche

    Une idée de la raison pour laquelle le thread pourrait s'arrêter?
    Merci

  9. #9
    Membre expérimenté

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

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    Par défaut
    Une idée de la raison pour laquelle le thread pourrait s'arrêter?
    Peut être en montrant le code de ton thread
    "It's more fun to compute !"

  10. #10
    Membre actif

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Points : 208
    Points
    208
    Par défaut
    D'accord et merci d'avance
    Code Delphi : 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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
     
    unit UJobCompress;
     
    interface
     
    uses
      Classes;
     
    type
      JobCompress = class(TThread)
      private
        { Private declarations }
        isCompression: boolean;
        isDecompression : boolean;
        fichierLecture : string;
      public
        procedure setCompression(nomFichier : string);
        procedure setDecompression(nomFichier : string);
      protected
        procedure Execute; override;
    	  procedure lancerCompression();
        procedure lancerDecompression();
      end;
     
    function compress(source : Pointer; dest : Pointer; taille : Longword) : Longword; stdcall; external 'comp.dll' name 'compress';
    function decompress(source : Pointer; dest : Pointer) : Longword; stdcall; external 'comp.dll' name 'decompress';
    function decompress_size(source : Pointer) : Longword; stdcall; external 'comp.dll' name 'decompress_size';
     
    implementation
     
    uses
    	ufonction, SysUtils, frmPrincipal;
     
    procedure JobCompress.setCompression(nomFichier : string);
    begin
    	isCompression := true;
      isDecompression := false;
      fichierLecture := nomFichier;
    end;
     
    procedure JobCompress.setDecompression(nomFichier : string);
    begin
    	isCompression := false;
      isDecompression := true;
      fichierLecture := nomFichier;
    end;
     
    procedure JobCompress.Execute;
    begin
    	if isCompression = true then
      begin
        lancerCompression();
      end;
     
      if isDecompression = true then
      begin
    		lancerDecompression();
      end;
    end;
     
    procedure JobCompress.lancerDecompression();
    var
    	tailleFinale : LongWord;
      fichierDecompresse : TMemoryStream;
      fichierCompresse : TMemoryStream;
      nomNouveauFichier : string;
    begin
    	//récupère le nom du fichier et remplace son extension
    	nomNouveauFichier := ExtractFilePath(fichierLecture) + extractFileNameWithoutExtension(ExtractFileName(fichierLecture)) + '.dat';
     
    	try
      		//crée les zones
          fichierCompresse := TMemoryStream.Create();
          fichierDecompresse := TMemoryStream.Create();
     
          //chargement du fichier compressé en mémoire
          fichierCompresse.LoadFromFile(fichierLecture);
     
          //récupère sa taille finale
          tailleFinale := decompress_size(fichierCompresse.Memory);
          fichierDecompresse.Size := tailleFinale;
     
          //décompresse le fichier compressé
          decompress(fichierCompresse.Memory,fichierDecompresse.Memory);
     
          //écriture du fichier décompressé
          fichierDecompresse.SaveToFile(nomNouveauFichier);
     
    	finally
    			fichierCompresse.free;
          fichierDecompresse.Free;
    	end;
     
    end;
     
    procedure JobCompress.lancerCompression();
    var
    	tailleFinale : LongWord;
      fichierDecompresse : TMemoryStream;
      fichierCompresse : TMemoryStream;
      nomNouveauFichier : string;
    begin
    	//récupère le nom du fichier et remplace son extension
    	nomNouveauFichier := ExtractFilePath(fichierLecture) + extractFileNameWithoutExtension(ExtractFileName(fichierLecture)) + '.cdat';
     
    	try
      		//crée les zones
          fichierDecompresse := TMemoryStream.Create();
          fichierCompresse := TMemoryStream.Create();
     
          //chargement du fichier décompressé en mémoire
          fichierDecompresse.LoadFromFile(fichierLecture);
     
          //donne la même taille au fichier compressé
          fichierCompresse.Size := fichierDecompresse.Size;
     
          //compresse le fichier
          tailleFinale := compress(fichierDecompresse.Memory,fichierCompresse.Memory,fichierDecompresse.Size);
     
          //mise à jour de la taille du fichier compressé
          fichierCompresse.size := tailleFinale;
     
          //écriture du fichier compressé
          fichierCompresse.SaveToFile(nomNouveauFichier);
    	finally
    			fichierCompresse.free;
          fichierDecompresse.Free;
    	end;
    end;
     
    end.

  11. #11
    Membre actif

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 310
    Points : 208
    Points
    208
    Par défaut
    Est-ce que tu as eu l'occasion de regarder mon code? Je suis toujours bloqué pour ça :/ Merci

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