AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Record zu Array of Byte

Ein Thema von DerSascha · begonnen am 16. Dez 2005 · letzter Beitrag vom 19. Dez 2005
Antwort Antwort
DerSascha

Registriert seit: 14. Jan 2004
Ort: Niedersachsen
18 Beiträge
 
Delphi 7 Enterprise
 
#1

Record zu Array of Byte

  Alt 16. Dez 2005, 15:09
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:
  TBitmapCoreHeader = record // 14 Bytes
    Signature :UInt16; // 'BM'
    FileSize :UInt32; // Dateigröße in Bytes
    Reserved :UInt32; // Unbenutzt
    DataOffset :UInt32; // Datenaufsatzpunkt (Offset)
  end;
Nun hab ich da ein gefülltes Record FBitmapCoreHeader und möchte das als einfaches Array of Byte (TBytes) haben.

Habe sowas wie StructureToBytes(TObject(FBitmapCoreHeader)) probiert, aber das ist plattformspezifisch und schmeißt zudem
eine Exception .

Gruss,
Sascha
  Mit Zitat antworten Zitat
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#2

Re: Record zu Array of Byte

  Alt 16. Dez 2005, 15:30
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;
??
  Mit Zitat antworten Zitat
DerSascha

Registriert seit: 14. Jan 2004
Ort: Niedersachsen
18 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Record zu Array of Byte

  Alt 16. Dez 2005, 15:45
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
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#4

Re: Record zu Array of Byte

  Alt 16. Dez 2005, 15:54
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
  Mit Zitat antworten Zitat
DerSascha

Registriert seit: 14. Jan 2004
Ort: Niedersachsen
18 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: Record zu Array of Byte

  Alt 16. Dez 2005, 16:26
Hallo,

Zitat:
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
Wo ist der Zusammenhang? Ich möchte ja gerade ein Array of Byte haben aus einer Struktur (einem Record).

Zitat:
Was aber das eigentliche Problem angeht, so ist das von brechi gepostete Array schon passend.
Öh, wie gesagt das funktioniert nicht. Ich glaube mittlerweile, dass ich das ganze über die Klasse System.Reflection
machen muß. Nur ist mir noch nicht ganz klar wie .

Gruss,
Sascha
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#6

Re: Record zu Array of Byte

  Alt 16. Dez 2005, 18:37
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;
}
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
DerSascha

Registriert seit: 14. Jan 2004
Ort: Niedersachsen
18 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: Record zu Array of Byte

  Alt 16. Dez 2005, 18:45
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
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.481 Beiträge
 
Delphi 10.1 Berlin Professional
 
#8

Re: Record zu Array of Byte

  Alt 16. Dez 2005, 21:19
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;
  Mit Zitat antworten Zitat
DerSascha

Registriert seit: 14. Jan 2004
Ort: Niedersachsen
18 Beiträge
 
Delphi 7 Enterprise
 
#9

Re: Record zu Array of Byte

  Alt 19. Dez 2005, 18:51
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:
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;
Der Versuch über System.Reflection tut leider nicht und mir ist natürlich nicht klar warum, aber ich poste das hier troztdem .
Delphi-Quellcode:
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;
Was mir noch aufgefallen ist:
  • Records müssen packed sein und offenbar mit dem Attribut [StructLayout(LayoutKind.Sequential)] deklariert werden, damit sie ge"marshalled" werden können
  • Es scheint etwas mühsam die Größe eines Aufzählungstyps zu erzwingen: Mein Weg ist ${Z4} plus [MarshalAs(UnmanagedType.U4)] um ein "WrapperRecord" (Erzwingen einer Breite von hier z.B. 4 Byte. Für bessere Ideen hab ich immer ein offenes Ohr. Das sieht nämlich ziemlich unschön aus

Delphi-Quellcode:
  {$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;
Vielen Dank,
Sascha
  Mit Zitat antworten Zitat
Antwort Antwort


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 14:21 Uhr.
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