Brauche Hilfe bei struct-Aufbau (StructLayout-Attribut)



  • Keiner ne Idee ?



  • z.B. so:

    using System;
    using System.IO;
    
    namespace Test
    {
    	public struct S
    	{
    		public long v_0;	// 8 bytes
    		public int v_1;	// 4 bytes
    		public char v_2;	// 2 bytes
    		public byte v_3;	// 1 byte
    	}
    
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			const int length = 15;
    			byte[] data = new byte[length];
    			for (int i = 0; i < data.Length; ++i)
    			{
    				data[i] = (byte) i;
    			}
    
    			using (MemoryStream stream = new MemoryStream(data))
    			{
    				using (BinaryReader reader = new BinaryReader(stream))
    				{
    					S s = new S();
    					s.v_0 = reader.ReadInt64();
    					s.v_1 = reader.ReadInt32();
    					s.v_2 = reader.ReadChar();
    					s.v_3 = reader.ReadByte();
    				}
    			}
    		}
    	}
    }
    

    Edit:
    Auf der Basis kannst Du dann auch mit Reflection deine Struktur automatisch füllen (Member für Member je nach Typ).



  • Ahja ok, super, danke dir !

    Nur noch eine Frage:
    Wieso ergibt ein sizeof(MyStruct) 4 Byte, obwohl short = 2 Byte und char = 1 Byte ??:

    [StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
    public struct MyStruct
    {
        public short val;
        public char rad;
    }
    

    Selbst mit Pack (oder Size) funktioniert es nicht !

    Woher kommt das 1 Byte ? 😕
    Genau deshalb füllt es mir auch meine Struktur falsch.



  • Weil ein Char in .NET eben 16bit breit ist.
    Simon



  • Ok gut.

    Und habe das Problem gelöst, die struct muss so aussehen, dass sie 3 Byte ergibt:

    [StructLayoutAttribute(LayoutKind.Explicit)]
    public struct MyStruct
    {
        [FieldOffsetAttribute(0)]
        public short val;
        [FieldOffsetAttribute(1)]
        public char rad;
    }
    

    Und noch hier und da ein Pack = 1, ein FieldOffsetAttribute...

    Die Größe von 53 Bytes hat die struct erstmal, nun muss das Füllen mit dem byte-Array noch klappen.

    Aber ich danke dir trotzdem vielmals für die Hilfe !!! 👍



  • Bist Du sicher, dass das das ist was Du möchtest?
    So ist deine Struktur zwar 3 Byte gross, aber der short und der char ist überlapped, da char nunmal 2 Byte gross ist.

    Simon



  • Entschuldige, ich habe in dieser Struktur ein short und ein byte !

    Hatte vergessen es zu ändern !
    So passt es dann.

    Mal eine andere Frage (ja ich weiß, ich nerve 🙂 ):
    Wie würdest du eine Struktur Byte für Byte mit dem Inhalt eines byte oder char-Arrays befüllen ??

    Wie würdest du das machen ?
    Denn ich habe dazu diese URL gefunden: http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx
    Nur klappt das bei mir nicht ganz: er soll Byte für Byte schreiben, schreibt aber immer nur jedes 2. Byte statt jedes !



  • Wie würdest du eine Struktur Byte für Byte mit dem Inhalt eines byte oder char-Arrays befüllen ??

    So wie beschrieben mit dem BinaryReader (ev. ausgebaut mit Reflection).

    Simon



  • Hey sry für die späte Meldung !

    Also mit dem BinaryReader hole ich mir ja die Daten vom Port:

    BinaryReader reader = new BinaryReader(serialPort.BaseStream);
    byte[] InputBuffer = new byte[4096];
    InputBuffer = reader.ReadBytes(BytesReceived);
    

    So, die Daten liegen auf jeden Fall korrekt vor.
    Ich könnte als "Notlösung" dem struct jedes Byte einzeln zuweisen. Das würde funktionieren und auch am Ende passn.

    Nur wäre es schöner, wenn ich genau Byte für Byte kopieren könnte.

    Und um ehrlich zu sein, ich hab von Reflection nicht wirklich Ahnung, ich mache C# / .NET eher "nebenbei".
    Hab mich mit Reflection noch nicht auseinandergesetzt.



  • Das new byte[] ist überflüssig!

    BinaryReader reader = new BinaryReader(serialPort.BaseStream);
    byte[] InputBuffer = reader.ReadBytes(BytesReceived);
    

    Also mit dem BinaryReader hole ich mir ja die Daten vom Port:

    Nein! Mit dem BinaryReader interpretierst Du die Daten und wandelst sie dann in die Basis Typen (int, float, was weiss ich alles) um.
    Guck Dir mein Beispiel in diesem Thread an!

    Und um ehrlich zu sein, ich hab von Reflection nicht wirklich Ahnung, ich mache C# / .NET eher "nebenbei".
    Hab mich mit Reflection noch nicht auseinandergesetzt.

    Das war ja auch nur als Inspiration gedacht um die Dinge noch ein wenig zu automatisieren, ist nicht wirklich nötig.

    Simon



  • theta schrieb:

    Das new byte[] ist überflüssig!

    Ok, hast Recht ! Danke 😉

    Nein! Mit dem BinaryReader interpretierst Du die Daten und wandelst sie dann in die Basis Typen (int, float, was weiss ich alles) um.

    Stimmt ja, die Angabe des Basestreams des Serialports im ctor ist ja nicht umsonst ! 🙂

    Guck Dir mein Beispiel in diesem Thread an!

    Gut, ich habe es jetzt nun auch endlich gelöst !
    Die Daten liegen korrekt in der struct vor.

    Habe es einfach so gemacht:

    GCHandle pinnedStruct = GCHandle.Alloc(mystruct, GCHandleType.Pinned);
    Marshal.Copy(Buffer, 0, pinnedStruct.AddrOfPinnedObject(), Size);
    pinnedStruct.Free();
    

    Sollte soweit passen !

    Ich danke dir vielmals für: die Aufklärung, Tipps, Hilfe und deine Geduld mit mir !!! 🙂

    Noch nen schönen Sonntag ! 👍


Anmelden zum Antworten