2016-04-28 3 views
1

Ich habe die nächste Funktion in C# und ich muss zu Delphi konvertieren. C# hat BitConverter, um es einfach zu machen, aber ich weiß nicht, wie man in Delphi vorgeht.Verschieben von C# -Funktion nach Delphi

/// Reads a 4-byte floating point value from the current stream 
public override float ReadSingle(float sg) 
{ 
    byte[] temp = BitConverter.GetBytes(sg); 
    Array.Reverse(temp); 
    float returnVal = BitConverter.ToSingle(temp, 0); 
    return returnVal; 
} 

ich getan habe:

procedure ReverseBytes(Source, Dest: Pointer; Size: Integer); 
var 
    Index: Integer; 
begin 
    for Index := 0 to Size - 1 do 
    Move(Pointer(LongInt(Source) + Index)^, 
     Pointer(LongInt(Dest) + (Size - Index - 1))^ , 1); 
end; 
function GetBytes(sg:single):Tbytes; 
begin 
    result:=?????? 
end; 

function ReadSingle(sg:single):single; 
var dest,temp:Tbytes; 
begin 
temp := GetBytes(sg); //How todo ??? 
ReverseBytes(temp,dest,length(temp)); 
result:=dest; 
end; 
+0

versuchen Sie es hier - http://lingua.codegear.com/babelcode/ – MethodMan

+0

@MethodMan Vielen Dank, aber ich bekomme einen Fehler beim Zugriff auf diese Website. Vielleicht mein Internetanbieter? –

+1

'ReverseBytes (@ sg, @ Ergebnis, SizeOf (Single));' ist alles was Sie brauchen. –

Antwort

3

Sie versuchen Schwimmer in Big-Endian-Darstellung in ein Little-Endian zu konvertieren.

Diese Funktion wird das für Sie tun:

function ReadSingle(sg:single):single; 
begin 
    ReverseBytes(@sg,@Result,SizeOf(Single)); 
end; 

Moderne Delphi-Versionen mit TSingleHelper können die Bytes wie folgt umkehren:

function ReadSingle(sg:Single):single; 
begin 
    Result.Bytes[0] := sg.Bytes[3]; 
    Result.Bytes[1] := sg.Bytes[2]; 
    Result.Bytes[2] := sg.Bytes[1]; 
    Result.Bytes[3] := sg.Bytes[0]; 
end; 

Hinweis: Gleitkomma-Argumente übergeben wird im FPU-Register. Das Laden eines defekten Floats in das FPU-Register kann Ausnahmen auslösen. Ich würde es lieber vermeiden, die eingehenden Daten als Floats zu behandeln, bis die Byte-Reihenfolge korrigiert ist.

Ein Beispiel:

function ReadSingle(sg:PSingle): Single; 
begin 
    ReverseBytes(sg,@Result,SizeOf(Single)); 
end; 

Wie @Rudy wies darauf hin, die ReverseBytes Funktion ist nicht richtig für die 64-Bit-Compiler. Die LongInt() Modelle müssen an beiden Stellen durch NativeUInt() ersetzt werden. Dann funktioniert es sowohl für die 32-Bit-Compiler als auch für die 64-Bit-Compiler. Und es gibt Systemfunktionen zu verwenden, ntohl() in der winsock Bibliothek.


Hier ist eine weitere ReverseBytes Alternative von here:

procedure ReverseBytes(Source, Dest: Pointer; Size: Integer); 
begin 
    Dest := PByte(NativeUInt(Dest) + Size - 1); 
    while (Size > 0) do 
    begin 
    PByte(Dest)^ := PByte(Source)^; 
    Inc(PByte(Source)); 
    Dec(PByte(Dest)); 
    Dec(Size); 
    end; 
end; 
+0

Tut mir leid, aber woher weißt du, dass ich eine Big-Endian-Repräsentation habe? –

+0

Kann ich dasselbe tun, um den Typ zu verdoppeln, indem ich einfach nur das Doppelte ändere? –

+0

Big Endian, auch bekannt als Netzwerk-Byte-Reihenfolge, ist ein gängiges Format in Motorola-CPUs und auch die Byte-Reihenfolge, in der Daten in vielen Protokollen übertragen werden. Es könnte auch eine Speicherkonvention in Datendateien sein. Windows-Computer sind Little Endian, und ich vermute, dass dies die Darstellung ist, die Sie wollen. (Es könnte aber auch andersherum sein). –

2

Für die Umsetzung von Netzwerk-Byteordnung (im Fall von Delphi, von Big-Endian zu Little-Endian), Gastgeber können Sie verwenden Sie die Funktionen ntohl und ntohs von WinSock oder WinSock2:

uses 
    WinSock2; 

type 
    PUInt32 = ^UInt32; 
    PUInt64 = ^UInt64; 

function ReadSingle(sg: Single): Single; 
begin 
    Result := ntohl(PUInt32(@sg)); 
end; 

function ReadDouble(db: Double): Double; 
begin 
    Result := UInt64(ntohl(PUInt64(@db) shr 32)) or 
      UInt64(ntohl(PUInt32(@db))) shl 32; 
end; 

oder, wenn Sie ReverseBytes verwenden möchten, aktualisieren Sie es dann in die Neuzeit:

function ReverseBytes(Source, Dest: Pointer; Size: Integer); 
var 
    I: Integer; 
begin 
    for I := 0 to Size - 1 do 
    PByte(Dest)[I] := PByte(Source)[Size - I - 1]; 
end; 

function ReadSingle(sg: Single): Single; 
begin 
    ReverseBytes(@sg, @Result, SizeOf(Single)); 
end; 

function ReadDouble(db: Double): Double; 
begin 
    ReverseBytes(@db, @Result, Sizeof(Double)); 
end; 

Wenn Sie eine ältere Version von Delphi haben, die nicht die Syntax PByte -as-Array erlaubt es, Sie PAnsiChar stattdessen verwenden können von PByte, aber shshshsh!, das ist ein Hack, erzähl anderen nicht, dass ich das gesagt habe.

+0

Vielen Dank, Herr Rudy. –

+0

Nur um es zu ergänzen. In C# habe ich public override lange ReadInt64() \t \t { \t \t \t Rückkehr IPAddress.NetworkToHostOrder (someInt64); \t \t}. Kann ich es in Delphi mit der Funktion ReadInt64() ersetzen: int64; beginne Ergebnis: = Gstack.NetworkToHost (someInt64); Ende; ohne Probleme. –

+0

Ja, ich denke schon. Sie sollten es versuchen und sehen, ob es das erwartete Ergebnis produziert, aber es sieht gut aus. –