![]() |
Record zu Array of Byte
Hallo,
weiss jemand wie ich in .NET ein Record in ein Array of Byte konvertiere ohne über solche Verrenkungen wie BinaryReader/Writer gehen zu müssen?
Delphi-Quellcode:
Nun hab ich da ein gefülltes Record FBitmapCoreHeader und möchte das als einfaches Array of Byte (TBytes) haben.
TBitmapCoreHeader = record // 14 Bytes
Signature :UInt16; // 'BM' FileSize :UInt32; // Dateigröße in Bytes Reserved :UInt32; // Unbenutzt DataOffset :UInt32; // Datenaufsatzpunkt (Offset) end; Habe sowas wie StructureToBytes(TObject(FBitmapCoreHeader)) probiert, aber das ist plattformspezifisch und schmeißt zudem eine Exception ;-). Gruss, Sascha |
Re: Record zu Array of Byte
Delphi-Quellcode:
??
type
uint16 = word; uint32 = dword; TBitmapCoreHeader = record // 14 Bytes Signature :UInt16; // 'BM' FileSize :UInt32; // Dateigröße in Bytes Reserved :UInt32; // Unbenutzt DataOffset :UInt32; // Datenaufsatzpunkt (Offset) end; TBarray = array[0..sizeOf(TBitmapCoreHeader)-1] of byte; PBarray = ^TBarray; procedure TForm1.FormCreate(Sender: TObject); var x: TBitmapCoreHeader; y: PBArray; begin y := @x; |
Re: Record zu Array of Byte
Hallo Brechi,
Danke für deine Antwort. Leider scheint das unter .NET nicht zu funktionieren. Der Compiler meldet: [Fehler] bmp.pas(221): E2410 Unsichere Zeigervariablen, Parameter oder Konstanten sind nur in unsicheren Prozeduren zulässig [Fehler] bmp.pas(223): E2396 Unsicherer Code ist nur in unsicheren Prozeduren zulässig Das mit Zeigern ist für .NET unsicher und geht scheinbar nur im Zusammenhang mit unmanaged Code AFAIK. Gruss, Sascha |
Re: Record zu Array of Byte
Hi,
bin mir zwar nicht ganz sicher, aber würde mich doch sehr sehr stark wundern wenn in .Net Arrays nicht ohnehin als Zeiger übergeben werden. Wenn du also ein Array hast, wirst du so oder so kein Zeiger brauchen. Aber insbesondere aus Gründen der Typsicherheit wird .Net schon klug nur mit Pointern/Referenzen arbeiten und nicht wild Speicher kopieren, aber halt automatisch. Was aber das eigentliche Problem angeht, so ist das von brechi gepostete Array schon passend. Gruß Der Unwissende |
Re: Record zu Array of Byte
Hallo,
Zitat:
Zitat:
machen muß. Nur ist mir noch nicht ganz klar wie :-). Gruss, Sascha |
Re: Record zu Array of Byte
Statt eine Methode mit "unsafe" zu kennzeichnen, kannst du auf Marshaller ausweichen.
Irgendwo aus dem Netz gefischt:
Code:
static byte[] YourStructToBytes( test s )
{ int size = Marshal.SizeOf( s ); byte[] retArr = new byte[ size ]; IntPtr buf = Marshal.AllocHGlobal( size ); // create unmanaged memory Marshal.StructureToPtr ( s, buf, false ); // copy struct for (int i=0; i<size; ++i) { retArr[i] = Marshal.ReadByte(buf, i); // read unmanaged bytes } Marshal.FreeHGlobal( buf ); return retArr; } |
Re: Record zu Array of Byte
Hallo Sebastian,
das sieht wirklich gut aus. Ich werde das am Montag gleich ausprobieren. Ich mach jetzt aber erst mal Feierabend/WE. Ich glaube ich bekomme das mit Hilfe der System.Reflection auch noch hin. Ich schau dann mal was schneller geht. Ich denke es wird dein "gefischte" ;-) Beitrag sein. Reflection soll schnarchlangsam sein. Danke, Sascha |
Re: Record zu Array of Byte
Das ist doch ein wenig unperformant, wenn man für jedes Byte den Marshaller anwerfen muss.
Code:
int size = Marshal.SizeOf(myStruct);
byte[] retArr = new byte[size]; IntPtr p = Marshal.AllocHGlobal(size); try { Marshal.StructureToPtr(myStruct, p, false); Marshal.Copy(p, retArr, size); } finally { Marshal.FreeHGlobal(p); } return retArr; |
Re: Record zu Array of Byte
Hallo,
vielen Dank noch mal an alle. Die Konvertierung funktioniert nun wunderbar :-). So funktioniert die Konvertierung von (packed) Records in TBytes (Array of Byte). Das ist die 1:1-Umsetzung von Adreas Vorschlag. Die Aufrufparameter der Methode Copy mußten ein wenig angepaßt werden, weil es die Methode mit den Aufrufparametern so wohl nicht mehr existiert(?).
Delphi-Quellcode:
Der Versuch über System.Reflection tut leider nicht und mir ist natürlich nicht klar warum, aber ich poste das hier troztdem ;-).
class function THalloele.convertStructureToBytes(
astructure: System.Object):TBytes; var groesse: Integer; intp: IntPtr; begin groesse := Marshal.&SizeOf(astructure); SetLength(Result, groesse); intp := Marshal.AllocHGlobal(groesse); try Marshal.StructureToPtr(astructure, intp, false); Marshal.&Copy(intp, Result, 0, groesse); finally Marshal.FreeHGlobal(intp); end; end;
Delphi-Quellcode:
Was mir noch aufgefallen ist:
class function THalloele.reflect(struktur: System.Object):TBytes;
var ms :MemoryStream; typ: System.&Type; fields: Array of FieldInfo; i :Integer; value: TObject; puffer: TBytes; begin Result := nil; ms := MemoryStream.Create(); try try typ := TypeOf(struktur); fields := struktur.GetType.GetFields; for i := Low(fields) to High(fields) do begin value := fields[i].GetValue(struktur); puffer := TBytes(value); ms.Write(puffer, 0, Marshal.&SizeOf(fields[i].FieldType)); end; Result := ms.ToArray; except on e:Exception do begin e.Message; end; end; finally ms.Close; end; end;
Delphi-Quellcode:
Vielen Dank,
{$Z4}
TBitmapCompression = (BI_RGB = 0, BI_RLE8 = 1, BI_RLE4 = 2); [StructLayout(LayoutKind.Sequential)] TBitmapInfoheaderCompression = packed record [MarshalAs(UnmanagedType.U4)] CompressionType: TBitmapCompression; end; [StructLayout(LayoutKind.Sequential)] TBitmapCoreHeader = packed record // 14 Bytes Signature :UInt16; // 'BM' FileSize :UInt32; // Dateigröße in Bytes Reserved :UInt32; // Unbenutzt DataOffset :UInt32; // Datenaufsatzpunkt (Offset) end; [StructLayout(LayoutKind.Sequential)] TBitmapInfoHeader = packed record // 40 Bytes Size :UInt32; // Größe des InfoHeader (fest 40) Width :UInt32; // Bitmap-Breite Height :UInt32; // Bitmap-Höhe Planes :UInt16; // Anzahl der Ebenen/Planes (fest 1) BitCount :UInt16; // Bits pro Pixel // 1 = monochrome palette. NumColors = 1 // 4 = 4bit palletized. NumColors = 16 // 8 = 8bit palletized. NumColors = 256 // 16 = 16bit RGB. NumColors = 65536 (?) // 24 = 24bit RGB. NumColors = 16M Compression :TBitmapInfoheaderCompression; // Kompressionstyp // 0 = BI_RGB no compression // 1 = BI_RLE8 8bit RLE encoding // 2 = BI_RLE4 4bit RLE encoding ImageSize :UInt32; // (compressed) Size of Image // It is valid to set this =0 if Compression = 0 XpixelsPerM :UInt32; // horizontal resolution: Pixels/meter YpixelsPerM :UInt32; // vertical resolution: Pixels/meter ColorsUsed :UInt32; // Zahl der tatsächlich verwendeten Farben ColorsImportant :UInt32; // Anzahl der wichtigen Farben // 0 = all end; Sascha |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:55 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