Einzelnen Beitrag anzeigen

Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#21

Re: 7-zip Entpacker einbinden

  Alt 15. Mär 2008, 13:35
Zitat von xZise:
Ah okay. Ist etwas verwirrend Da muss man erstmal durchblicken
Was macht den genau TStreamReader?
TStreamReader implementiert die beiden Interfaces IInStrem und ISequentialInStream. Es muss ja irgendeine Schnittstelle geben über die dein Programm mit der DLL kommunizieren kann, und da nicht alle Programme in C++ geschrieben werden (so wie die DLL) muss diese Schnittstelle sprachenunabhängig sein - daher verwendet die DLL eben COM-Interfaces. Die ganze Kommunikation läuft folgendermaßen ab: du forderst ein Interface aus der DLL an (über die Funktion CreateObject, welche von der DLL exportiert wird). In meinem Fall (Packen) hab ich dazu eine IOutArchive-Instanz angefordert - du bräuchtest wohl eine IInArchive-Instanz. Ab dann läuft alles nur mehr über dieses Interface.
Zum Packen ruf ich die Methode IOutArchive.UpdateItems auf welche folgendermaßen ausschaut:
function UpdateItems(outStream: ISequentialOutStream; numItems: DWord; updateCallback: IArchiveUpdateCallback): HRESULT; stdcall; Es werden also zwei Interfaces erwartet - die Implementierung dieser Interfaces muss man selbst zur Verfügung stellen! Der outStream wird zum schreiben des Archivs benötigt, ich hab daher folgendes gemacht:
Delphi-Quellcode:
outStream := TStreamWriter.Create(TFileStream.Create(FParams.Filename, fmCreate)); // TStreamWriter ist der Wrapper für den TFileStream
FOutArchive.UpdateItems(outStream, FParams.Items.Count, callback);
Nachdem TStreamWriter das ISequentialOutStream Interface implementiert, kann eine TStreamWriter-Instanz als ISequentialOutStream verwendet werden (Delphi führt eine implizite Typumwandlung durch). Wenn die DLL jetzt Daten in das Archiv schreiben muss, so wird die Write-Methode des ISequentialOutStream Interfaces aufgerufen. Die Implementierung dieser Methode schaut bei mir so aus:
Delphi-Quellcode:
function TStreamWriter.Write(const data: Pointer; Size: DWord; processedSize: PDWord): HRESULT;
var
  writeCount: Integer;
begin
  try
    writeCount := FStream.Write(data^, Size);
    if Assigned(processedSize) then
      processedSize^ := writeCount;

    Result := S_OK;
  except
    Result := S_FALSE;
  end;
end;
TStreamWriter macht jetzt also nichts anderes als diese Write-Aufrufe an die Write-Methoden der internen TStream-Instanz weiter zu delegieren. In meinem Fall also an die TFileStream-Instanz die dem Constructor mitgegeben wurde, theroretisch kann man auch einen TMemoryStream, TBlobStream, ... verwenden (ob es sinnvoll ist ist zwar fraglich, es ist aber auf jeden Fall möglich).
Dasselbe gilt für das Callback-Interface - man muss eine eigene Implementierung dieses Interfaces zur Verfügung stellen, deren Methoden dann von der DLL aufgerufen werden. Den ganzen Ablauf im Detail zu erklären wäre jetzt zuviel, aber vielleicht hast du das Konzept jetzt verstanden und kannst dir den Rest alleine zusammensuchen.

Gruß, Motzi
Manuel Pöter
  Mit Zitat antworten Zitat