passage de TStream de Delphi à C++

passage de TStream de Delphi à C++ - Delphi/Pascal - Programmation

Marsh Posté le 25-06-2007 à 15:53:14    

J'ai un dll écrite avec Builder C++ dans laqu'elle j'ai une classe qui met permet de sauvegarder un fichier dans une base de donnée. Cette classe utilise donc naturellement un TStream en entrée.
 
Cependant, lorsque j'utilise cette dll depuis mon programme delphi, lorsque mon objet c++ veux acceder au TStream que Delphi lui a fourni, j'obtient une belle EAV

Violation d'accès à l'adresse 00000000. Lecture de l'adresse 00000000


 
C'est la premiere fois que j'obtient une erreur pareil avec des objets VCL.
la gestion des stream serait-elle différentes entre delphi et c++ builder ? comment faire dans ce cas la ?

Reply

Marsh Posté le 25-06-2007 à 15:53:14   

Reply

Marsh Posté le 02-07-2007 à 11:42:44    

Faut voir le code. Normalement ça marche, mais vu ton erreur ça ressemble plutôt à une variable non créée (NULL), donc peut-être que c'est la façon dont tu ouvres ton TStream.
Quand tu dis "le TStream que Delphi lui a fourni", tu entends quoi exactement ? Tu passes un objet à la DLL/de la DLL ?

Reply

Marsh Posté le 07-07-2007 à 20:46:31    

a un objet de la dll
en gros, j'appelle une méthode de la dll qui me renvoi un objet c++, sur lequel j'appele une méthode "setStream" avec un TStream créé en delphi
et quand ma dll C++ veux acceder a ce stream, bha ca me donne cette EAV
par contre le stream existe bien et est utilisable en delphi
 
 
en attendant, je passe par un fichier sur le disque mais ca me plais pas des masses.

Reply

Marsh Posté le 07-07-2007 à 21:55:01    

Je ne suis pas sûr qu'on puisse passer comme ça des objets. Par contre si tu fais ça avec des interfaces ça devrait passer sans problème. En gros il faut que ton objet dérive de IInterfacedObject en plus de sa classe parente actuelle.

Reply

Marsh Posté le 07-07-2007 à 22:46:38    

ca passe tres bien pour d'autres objects "home made" (tant qu'ils dérivent de TObject)
 
en fait on ne fait que passer un pointeur vers une zone mémoire, ensuite la VT fait le reste
 
j'ai l'impression que les TStream Delphi et les TStream C++Builder n'ont pas la meme VT donc on peut pas passer d'un a l'autre facilement
 
je suis dans une impasse puisque pour la sauvegarde dans la db, le TStream est crée coté delphi (et j'ai pas le choix vu que ca viens d'un composant externe) et pour la récupération depuis la db, c'est le C++ qui doit le créer :/

Reply

Marsh Posté le 08-07-2007 à 00:37:29    

C'est un composant dont t'as pas le code ? Parce que sinon les composants Delphi se compilent en Builder sans probleme en général.
 
Sinon pour ton stream, il reste la solution de passer un pointeur vers un bloc mémoire, plus basique que de passer tout l'objet TStream.
 
Code venant d'AMC : (mais du vieux, donc c'est peut-être du bricolage pour rien ou du code pas très propre)
 

Code :
  1. function TMovie.SaveToMemory: THandle;
  2. var
  3.  Stream: TMemoryStream;
  4.  DataPtr: Pointer;
  5. begin
  6.  Stream := TMemoryStream.Create;
  7.  try
  8.    WriteData(Stream);
  9.    Stream.Seek(0, soFromBeginning);
  10.    Result := GlobalAlloc(GMEM_MOVEABLE, Stream.Size);
  11.    if Result <> 0 then
  12.    begin
  13.      DataPtr := GlobalLock(Result);
  14.      if DataPtr <> nil then
  15.      begin
  16.        Move(Stream.Memory^, DataPtr^, Stream.Size);
  17.      end;
  18.    end;
  19.  finally
  20.    Stream.Free;
  21.  end;
  22. end;
  23.  
  24. class procedure TMovie.FreeMemory(DataHandle: THandle; OnlyUnlock: Boolean = False);
  25. begin
  26.  if DataHandle <> 0 then
  27.  begin
  28.    GlobalUnlock(DataHandle);
  29.    if not OnlyUnlock then
  30.      GlobalFree(DataHandle);
  31.  end;
  32. end;
  33.  
  34. procedure TMovie.LoadFromMemory(DataHandle: THandle);
  35. var
  36.  DataPtr: Pointer;
  37.  DataSize: Integer;
  38.  Stream: TMemoryStream;
  39. begin
  40.  if DataHandle <> 0 then
  41.  begin
  42.    DataPtr := GlobalLock(DataHandle);
  43.    if DataPtr <> nil then
  44.    begin
  45.      Stream := TMemoryStream.Create;
  46.      try
  47.        DataSize := GlobalSize(DataHandle);
  48.        Stream.SetSize(DataSize);
  49.        Move(DataPtr^, stream.Memory^, DataSize);
  50.        Stream.Seek(0, soFromBeginning);
  51.        ReadData(Stream);
  52.      finally
  53.        Stream.Free;
  54.        GlobalUnlock(DataHandle);
  55.      end;
  56.    end;
  57.  end;
  58. end;


 
Là je copiais le stream vers le bloc mémoire réservé, mais il y a peut-être moyen de faire le même genre de choses en récupérant directement le pointeur "data" du stream, si c'est une DLL appartement au soft ça devrait marcher vu qu'ils ont le même espace mémoire je suppose.


Message édité par antp le 08-07-2007 à 00:39:40

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 08-07-2007 à 12:55:52    

et il marche ce code ?
il y a pas un probleme lors du Stream.Free ?  
 
donc faut que je passe passe par des pointeurs ! pas top ca ...

Reply

Marsh Posté le 08-07-2007 à 14:45:27    

Bah en fait le truc là c'est que le stream n'était que temporaire (cf Move qui copie les données du stream vers la zone réservée).
Je n'utilisais qu'un pointeur pour être sûr de ne pas avoir de problème à cause des classes :D

Reply

Marsh Posté le 08-07-2007 à 14:52:19    

c'est a tester ...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed