AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Delphi Var Parameter in C++

Ein Thema von NickelM · begonnen am 8. Jul 2011 · letzter Beitrag vom 11. Jul 2011
Antwort Antwort
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#1

AW: Delphi Var Parameter in C++

  Alt 9. Jul 2011, 11:50
Hmm also die Funktion macht folgendes :

okay ich schreib mal den gesammten Code der Funktion rein. Es hängt nur an der einen. Die werte, wenn ich sie in C++ ausgeben stimmen auch.
Nur das mit PByte, wie ich es jetzt gemacht hab, geht nicht so...vermutlich immer Zugriefsverletzung unter C++. In Delphi funkt es.

Delphi-Quellcode:
//DLL Funktion
function ReadPackedFileData(PackFileHandle : Integer; DataPos : Integer; DataSize : Integer; var Bytes : PByte): Integer; stdcall;
var BytesStream : TBytesStream;
    ReadBytes,EndPackBytes : TBytes;
    RByte : Byte;
    ZLibStream : TZDecompressionStream;
begin
   FileSeek(PackFileHandle,DataPos,0);
   SetLength(ReadBytes,DataSize);
   If FileRead(PackFileHandle,ReadBytes[0],DataSize) = DataSize then
   begin
    BytesStream := TBytesStream.Create(ReadBytes);
    ZLibStream := TZDecompressionStream.Create(BytesStream);

    while ZLibStream.Read(RByte,1) = 1 do
    begin
    SetLength(EndPackBytes,High(EndPackBytes)+2);
    EndPackBytes[High(EndPackBytes)] := RByte;
    end;
    Result := High(EndPackBytes)+1;
    GetMem(Bytes,Result);
    Move(EndPackBytes[0],Bytes^,Result);
    ZLibStream.Free;
    BytesStream.Free;

   end
   else
   Result := -1;
end;
So funkt es in Delphi :

Delphi-Quellcode:
var I : Integer;
    Bytes : TBytes;
    BLength : Integer;
    PB : PByte;
begin
    If String(PackedFileInfo^.FileName) = FileName then
    begin
     BLength := ReadPackedFileData(FPackInfo.FileHandle,
     PackedFileInfo^.FileDataPos,
     PackedFileInfo^.FileSizeCompressed,
     PB);
     if BLength > -1 then
     begin
     SetLength(Bytes,BLength);
     System.Move(PB^,Bytes[0],BLength);
     Result := TMemoryStream.Create;
     Result.Write(Bytes[0],High(Bytes));
     Result.Position := 0;
     Bytes := nil;
     end;
    end;
end;

So und so versuch ich sie aufzurufen (die Integer werte stimmen...') :

Code:
typedef int (*TReadPackedFileData) (int ,int ,int, byte*&);

int main()
{
byte* bytes = NULL;
int Bcount;

//Dynamisch geladen
Bcount = ReadPackedFileData(Test1->FileHandle,Test2->FileDataPos,Test2->FileSizeCompressed, bytes);
}
Der Sinn davon ist das ich die entpackten Daten zurückgeben will.
Da es nicht wie in Delphi mit TBytes geht, wollte ich den Pointer auf den anfange (wie ich auch denke hinbekommen habe) zurückgeben.
Damit man dann mit C++ ähnlichen Funktionen wie Move von Delphi darauf zugreifen kann.
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.

Geändert von NickelM ( 9. Jul 2011 um 11:53 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#2

AW: Delphi Var Parameter in C++

  Alt 9. Jul 2011, 12:02
Delphi-Dynamische Arrays sind Compilermagic, die C so nicht kennt. Der übliche Weg in C ist entweder ein "byte[0]"-Array plus separater Längenangabe, oder ein Pointer auf den Array-Elementtyp, auch mit separater Längenangabe.
Beides ist dann zu Delphi kompatibel, wenn man in den Methoden einen Pointer auf das erste Element des Delphi-Arrays übergibt (@MyArray[0]), aber du musst in jedem Fall Länge separat mit übergeben lassen.

So ein Funktionskopf könnte in einer Delphi-DLL dann so aussehen:
Delphi-Quellcode:
procedure Foo(myArray: PByte; aLength: Integer);
var
  bytes: TByteArray;
begin
  SetLength(bytes, aLength);
  Move(bytes[0], myArray, aLength);
.
.
end;
Danach solltest du eine Kopie in "bytes" haben, die man mit den ganzen Komfort von Delphi ansprechen kann, obgleich nur ein Pointer plus Länge übergeben wurden. Falls das übergebene Array verändert werden soll, musst du es nachher natürlich zurück kopieren. Etwas "undelphiischer" wäre gleich die Verwendung von Pointerarithmetik wie in C, nicht ganz sooo schmuck, aber auch kein Beinbruch.

Ah, ich sehe grad, dass du das Array befüllen willst! Dann wirst du nicht umhin kommen eine Funktion anzubieten, die die erwartete Länge vorab liefert, weil das Array muss vom Host-Programm zuvor ja komplett reserviert werden. Üblich ist es dafür die selbe Funktion zu nehmen, welche die Länge als result hat, und wenn für den Container ein NULL (nil) übergeben wird, gibt's eben nur Länge ohne Daten. Der Host muss dann also 2x aufrufen, ein mal mit NULL, und danach mit korrekt dimensioniertem Array (=Pointer auf sein erstes Element).
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium ( 9. Jul 2011 um 12:05 Uhr)
  Mit Zitat antworten Zitat
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#3

AW: Delphi Var Parameter in C++

  Alt 11. Jul 2011, 00:50
Achso..du meinst ich muss im Hostprogramm erst den speicher reservieren und dan die Referenz zu dem PByte übergeben in C++?

Und in Delphi das mit GetMem kann mir dan sparen ober?
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.
  Mit Zitat antworten Zitat
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#4

AW: Delphi Var Parameter in C++

  Alt 11. Jul 2011, 17:14
Nun das mit PByte funkt soweit.

Jetzt ist mir ein Phänomen aufgefallen, was ich mir nicht erklären kann.

Folgender Code funkt (bitte auf die Reihenfolge achten):
Code:
ReadNextPackedFileInfo(Test1->FileHandle,Test2);
bytes = new byte[Test2->FileSizeUncompressed];
ReadPackedFileData(Test1->FileHandle,Test2, bytes);

cout << Test2->FileName; //Wird ausgeben ohne Fehler
cout << endl;
Folgender nicht:
Code:
ReadNextPackedFileInfo(Test1->FileHandle,Test2);
cout << Test2->FileName; //Wird ausgegeben aber danach Fehler
cout << endl;

bytes = new byte[Test2->FileSizeUncompressed];
ReadPackedFileData(Test1->FileHandle,Test2, bytes);
Was hat das mit Reihenfolge zutun?
FileName ist vom Typ PAnsiChar(Delphi) char*(C++) und ist in einem record/struct. Der Speicher wird in der DLL bei ReadNextPackedFileInfo initalisiert und von der PackDatei gelesen.

P.S. : Gibt es ne Seite wo es erklärt wird worauf man bei Dlls, wo mit mehren Programmiersprachen kompatible sein sollen, achten soll?
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.

Geändert von NickelM (11. Jul 2011 um 17:18 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:53 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz