Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Speicherreservierung / Verständnisfrage (https://www.delphipraxis.net/51915-speicherreservierung-verstaendnisfrage.html)

x000x 21. Aug 2005 22:43


Speicherreservierung / Verständnisfrage
 
Moin moin,

ich habe vor einiger Zeit hier im Forum diesen Thread gefunden.
Habe mir anhand der Informationen eine funktion gebastelt, die mir ein Jpeg aus einer Resource lädt.
Delphi-Quellcode:
function LoadPictureFromRes(Instance: THandle; const szResName, szResType : String; var pPicture: IPicture) : Boolean;
const IID_IPicture : TGUID = '{7BF80980-BF32-101A-8BBB-00AA00300CAB}';
var
   hResInfo,
   hResGlobal : THandle;
   dwResSize  : DWord;
   pResData   : Pointer;
   //
   hMem       : THandle;
   pData      : Pointer;
   //
   hRslt      : HResult;
   pStream    : IStream;
Begin
   Result  := False;
   hResInfo := FindResource(Instance, Pointer(szResName), Pointer(szResType));
   if hResInfo = 0 then
      Exit;
   hResGlobal := LoadResource(Instance, hResInfo);
   if hResGlobal = 0 then
      Exit;
   hMem  := 0;
   try
      pResData := LockResource(hResGlobal);
      if Not Assigned(pResData) then
        Exit;

      dwResSize := SizeofResource(Instance, hResInfo);
      if dwResSize = 0 then
         Exit;

      hMem := GlobalAlloc(GHND or GMEM_NODISCARD, dwResSize);
      if hMem = 0 then
         Exit;

      pData := GlobalLock(hMem);
      if Not Assigned(pData) then
         Exit;

      Move(pResData^, pData^, dwResSize);
      GlobalUnlock(hMem);

      pStream := nil;
      hRslt  := CreateStreamOnHGlobal(hMem, True, pStream);
      if FAILED(hRslt) or (pStream = nil) then
         Exit;

      hRslt := OleLoadPicture(pStream, dwResSize, False, IID_IPicture, pPicture);
      if (hRslt = S_OK) and (pPicture <> nil) then
         Result := True;
   finally
      pStream := nil;
      if hMem <> 0 then
         GlobalFree(hMem);
      if hResGlobal <> 0 then
         FreeResource(hResGlobal);
   end;
end;
Sie funktioniert, nur habe ich dabei ein Verständnis Problem:
Ich lade das Image aus der Resource mit MSDN-Library durchsuchenLoadResource welche mir ein Handle
auf einen Speicherbereich liefert (HGLOBAL).
Die Funktion MSDN-Library durchsuchenCreateStreamOnHGlobal erwartet als ersten Parameter ebenfalls
ein Handle auf einen Speicherbereich vom Type HGlobal.
Warum muss ich den Zwischenschritt mit MSDN-Library durchsuchenGlobalAlloc und Move machen damit ich
letztendlich an die Daten komme?

Davon mal abgesehen, würde ich gerne auf GlobalAlloc verzichten. Mein Win32API Buch (http://www.amazon.de/exec/obidos/ASIN/3932311051/delphipraxis-21)
sagt mir, dass GlobalAlloc und Konsorten Relikte aus der Win16 Zeit sind und intern auf die Virtual-Funktionen
abgebildet werden.
Jeder Versuch die Virtual* -Funktionen hiermit (CreateStreamOnHGlobal) zu nutzen, schlug fehl.

Was genau ist denn bei den Virtual* funktionen anders und warum funktioniert CreateStreamOnHGlobal nur mit
GlobalAlloc?
Wäre vieleicht mal jemand so lieb/nett und könnte mir das mal erklären?
*liebgrins*

Luckie 21. Aug 2005 23:06

Re: Speicherreservierung / Verständnisfrage
 
Wie alt ist das Buch? Im aktuellen PSDK stzeht nichts davon, dass diese Funktion veraltet wäre. Da steht nur:
Zitat:

Note The global functions are slower than other memory management functions and do not provide as many features. Therefore, new applications should use the heap functions.
aber nichts von veraltet.

Olli 21. Aug 2005 23:41

Re: Speicherreservierung / Verständnisfrage
 
Zitat:

Zitat von Luckie
Wie alt ist das Buch?

7 Jahre. Erste Auflage 1998, 2te 1999 und 3te 2000. Ich habe die 3te hier vor mir.

Zitat:

Zitat von Luckie
Im aktuellen PSDK stzeht nichts davon,

Ich würde doch auch dringend das PSDK anraten!

Olli 21. Aug 2005 23:45

Re: Speicherreservierung / Verständnisfrage
 
Code kopiert und nicht verstanden? :zwinker: ... das rot markiert müßtest du komplett weglassen können. Das diente im Ursprungscode ja nur dem Kopieren der Daten aus der Datei in einen allozierten Speicherbereich. Da du aber bereits ein Handle hast, kannst du dir das sparen.
Code:
function LoadPictureFromRes(Instance: THandle; const szResName, szResType : String; var pPicture: IPicture) : Boolean;
const IID_IPicture : TGUID = '{7BF80980-BF32-101A-8BBB-00AA00300CAB}';
var
   hResInfo,
   hResGlobal : THandle;
   dwResSize  : DWord;
   pResData   : Pointer;
   //
   hMem       : THandle;
   pData      : Pointer;
   //
   hRslt      : HResult;
   pStream    : IStream;
Begin
   Result  := False;
   hResInfo := FindResource(Instance, Pointer(szResName), Pointer(szResType));
   if hResInfo = 0 then
      Exit;
   hResGlobal := LoadResource(Instance, hResInfo);
   if hResGlobal = 0 then
      Exit;
   hMem  := 0;
   try
[color=red]     pResData := LockResource(hResGlobal);
      if Not Assigned(pResData) then
        Exit;

      dwResSize := SizeofResource(Instance, hResInfo);
      if dwResSize = 0 then
         Exit;

      hMem := GlobalAlloc(GHND or GMEM_NODISCARD, dwResSize);
      if hMem = 0 then
         Exit;

      pData := GlobalLock(hMem);
      if Not Assigned(pData) then
         Exit;

      Move(pResData^, pData^, dwResSize);
      GlobalUnlock(hMem);[/color]

      pStream := nil;
      hRslt  := CreateStreamOnHGlobal(hMem, True, pStream);
      if FAILED(hRslt) or (pStream = nil) then
         Exit;

      hRslt := OleLoadPicture(pStream, dwResSize, False, IID_IPicture, pPicture);
      if (hRslt = S_OK) and (pPicture <> nil) then
         Result := True;
   finally
      pStream := nil;
      if hMem <> 0 then
         GlobalFree(hMem);
      if hResGlobal <> 0 then
         FreeResource(hResGlobal);
   end;
end;

x000x 22. Aug 2005 20:56

Re: Speicherreservierung / Verständnisfrage
 
Moin moin,
Zitat:

Zitat von Olli
Code kopiert und nicht verstanden? :zwinker: ... das rot markiert müßtest du komplett weglassen können. Das diente im Ursprungscode ja nur dem Kopieren der Daten aus der Datei in einen allozierten Speicherbereich. Da du aber bereits ein Handle hast, kannst du dir das sparen.

Zitat:

Zitat von x000x
... welche mir ein Handle auf einen Speicherbereich liefert (HGLOBAL).
... erwartet als ersten Parameter ebenfalls ein Handle auf einen Speicherbereich vom Type HGlobal.
... Warum muss ich den Zwischenschritt mit GlobalAlloc und Move machen damit ich
letztendlich an die Daten komme?

@Olli: Standard Satz geschrieben und meinen 1. Beitrag nicht gelesen? :zwinker:

Jetzt aber mal im ernst, genau das habe ich mir auch so gedacht und mich gewundert warum es
denn nicht funktioniert. Und dafür wollte ich eine Erklärung haben, da ich genau Das nicht verstehe.
Sorry, falls ich mich missverständlich ausgedrückt habe :oops:

@Luckie: Ich habe die 1. Auflage von diesem Buch und werde in Zukunft das PSDK befragen...

[Edit] Hatte Luckie falsch geschrieben [/Edit]

Luckie 22. Aug 2005 21:05

Re: Speicherreservierung / Verständnisfrage
 
Zitat:

Zitat von x000x
[Edit] Hatte Luckie falsch geschrieben [/Edit]

Es sei dir noch einmal verziehen. ;)

Olli 22. Aug 2005 22:06

Re: Speicherreservierung / Verständnisfrage
 
Zitat:

Zitat von x000x
@Olli: Standard Satz geschrieben und meinen 1. Beitrag nicht gelesen? :zwinker:

Gelesen schon, aber dann wohl mißverstanden. Könntest du bitte mal ein kleines Projekt posten, damit ich mir nicht alles zusammensuchen muß. Dann würde ich es mir mal schnell in Aktion anschauen. Danke.

Zitat:

Zitat von x000x
Jetzt aber mal im ernst, genau das habe ich mir auch so gedacht und mich gewundert warum es
denn nicht funktioniert. Und dafür wollte ich eine Erklärung haben, da ich genau Das nicht verstehe.

Es kann dann eigentlich nur noch mit den Speicherseiten zu tun haben. Vermutlich hat man auf das Handle nicht vollen Zugriff, was aber zB für die unten aufgerufene Funktion benötigt wird.

Olli 22. Aug 2005 22:13

Re: Speicherreservierung / Verständnisfrage
 
So, vergiß das Gesagte. Wäre ich nicht zu faul :oops: gewesen mal ins PSDK zu schauen, hätte ich die Lösung sofort gesehen. Das Handle welches MSDN-Library durchsuchenFindResource() zurückliefert ist nicht vom Typ HGLOBAL! Stattdessen ist es HRSRC. Unter Delphi ist das nicht wichtig, C oder C++ hätten vermutlich (?) gemeckert. Jedenfalls ist es kein HGLOBAL und somit auch kein Handle im Sinne von MSDN-Library durchsuchenGlobalAlloc().

Damit wäre das Rätsel gelöst. Die Daten müssen also mindestens einmal kopiert werden.

Nachtrag:
:wall: ... und wenn ich jetzt noch bei allen beiteiligten Funktionen nachgeguckt hätte, wäre mir folgendes aufgefallen
Dokumentation von LockResource() im PSDK 2003:
hResData
[in] Handle to the resource to be locked. The LoadResource function returns this handle. Note that this parameter is listed as an HGLOBAL variable only for backwards compatibility. Do not pass any value as a parameter other than a successful return value from the LoadResource function.

x000x 23. Aug 2005 00:15

Re: Speicherreservierung / Verständnisfrage
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin moin,

Zitat:

Zitat von Olli
Das Handle welches FindResource () zurückliefert ist nicht vom Typ HGLOBAL!

Ok, wenn ich ehrlich bin, habe ich dich auch nicht so verstanden, dass ich allein mit FindResource auskomme.
Ich hatte eher daran gedacht, LoadResource zu verwenden, da hier ein HGLOBAL zurückgegeben wird. Das es allerdings
auch nicht wirklich ein Handle auf einen Globalen Speicherblock zurückliefert, habe ich auch erst eben nach
deinem Post gelesen :oops:

Nur was ist denn der eigentliche Unterschied? Wenn ich eine Resource in den Speicher lade, befindet sich diese
doch auch "nur im Speicher"?! :gruebel:

Und warum kann ich nicht mit den Virtual** funktionen auf diesen Speicher zugreifen?
Diese funktionen sind doch auch nur für "Speicher-" zugriffe etc. da?!
Es wäre schön, wenn Ihr mir ein paar Links empfehlen könntet, wo ich derartiges
(Unterschiede Virtueller-/Globaler-/loakaler-/Heap- Speicher) mal nachlesen kann...

So, ich habe jetzt dochmal ein Testprojekt zusammengestellt, falls es doch noch jemanden interessiert,
bzw. jemand Sourcen zum testen des oben angesprochenen braucht...

[OT]
Die verwendetet Buttonklasse ist noch nicht fertig und meine Erste ohne die VCL... Also wenn Ihr
hier eurer Meinung nach Sinnloses Zeug drin findet (findet Ihr bestimmt), dann lasst es mich doch bitte wissen...
(Was nicht heisst, dass ich hier bewusst "Sinnloses Zeugs" geschrieben habe)
(Ich möchte keine Codebeispiele haben, sondern dann nur sachlich begründete Aussagen)
[/OT]

Olli 23. Aug 2005 00:25

Re: Speicherreservierung / Verständnisfrage
 
HGLOBAL steht übrigens nur in älteren Doks. - in den neuen ist's HRSRC!

Zitat:

Zitat von x000x
Nur was ist denn der eigentliche Unterschied? Wenn ich eine Resource in den Speicher lade, befindet sich diese doch auch "nur im Speicher"?! :gruebel:

Du lädst sie ja nicht, sondern ermittelst nur ein Handle bzw. ein Pointer auf die Ressource. In den meisten Fällen dürfte sie bereits vom PE-Loader mitgeladen worden sein - ansonsten wird sie nachgeladen. Allerdings ist dies dann in Form von MMFs.

Zitat:

Zitat von x000x
Und warum kann ich nicht mit den Virtual** funktionen auf diesen Speicher zugreifen?
Diese funktionen sind doch auch nur für "Speicher-" zugriffe etc. da?!
Es wäre schön, wenn Ihr mir ein paar Links empfehlen könntet, wo ich derartiges
(Unterschiede Virtueller-/Globaler-/loakaler-/Heap- Speicher) mal nachlesen kann...

Hatten wir letztens mit Luckie: die Heapfunktionen erlauben den Zugriff auf einen beliebigen Heap (ja ein Prozeß kann mehrere davon haben. Die Virtualfunktionen erlauben das prinzipiell auch für andere Prozesse und die Local*/Global*-Funktionen sind eigentlich Überbleibsel aus Win16. Ich werde mir aber eben nochmal anschauen wie die im Disassembler aussehen und dir dann bescheidgeben. Kann aber auch sein, daß ich es dann erstmal beseitelege und später fortfahre. Notfalls mußt du mich per PN erinnern.

Zitat:

Zitat von x000x
Die verwendetet Buttonklasse ist noch nicht fertig und meine Erste ohne die VCL... Also wenn Ihr hier eurer Meinung nach Sinnloses Zeug drin findet (findet Ihr bestimmt), dann lasst es mich doch bitte wissen...

Ich werde auch eine schreiben und ebenfalls eine Hyperlink-Klasse. Aber zuerst mache ich das alles in C und danach dann nochmal in Delphi ;)

Zitat:

Zitat von x000x
(Ich möchte keine Codebeispiele haben, sondern dann nur sachlich begründete Aussagen)

Waren unsere Aussagen bisher so schlimm? ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:19 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz