C# struct innerhalb einer struct

Gast #2955290
Lesenswert?
• ▲
▼
Hallo!

Da ich momentan echt nicht weiter weiß und mit C# noch nicht viel 
gemacht habe, frage ich mal hier die Experten. Habe einen PIC der mir 
über die serielle Schnittstelle auf Anforderung aktuelle Daten wie 
Temperatur, Motorpositionen usw. schicken soll. Am PIC habe ich alle 
relevanten Werte in einer struct stehen, die sich wiederum aus einzelnen 
selbstdefinierten Typen besteht (also auch nur struct).
Sieht dann z.B. so aus:
1
typedef struct
2
{
3
  // Allgemein
4
  signed short Temperatur;
5
  struct StepperMotor MotorA;
6
} werte;

Auch wenn sich viele mit dem Stil nicht anfreunden können, arbeite ich 
schon einige Jahre auf diese Art :)
Mir geht es nun darum, die struct "werte" in meiner C#-Anwendung 
auszuwerten. Die Kommunikation funktioniert einwandfrei, nur bekomme ich 
es mit C# nicht in den Griff, eine Struktur wie oben innerhalb einer 
anderen zu erstellen. In C# habe ich die obrige struct so angelegt:
1
[StructLayout(LayoutKind.Sequential, Size = 56)]
2
    public struct werte
3
    {
4
        public SByte Temperatur;
5
        public StepperMotor MotorA;
6
    };
Nun Initialisiere ich in meinem C#-Programm die struct so
1
private werte aktWerte = new werte();
und möchte dann eben z.B. per aktWerte.MotorA.steps den Wert in einer 
Textbox anzeigen lassen.

Meine Daten kommen in Telegrammform und nicht in Klartext. Ich schicke 
die struct werte wirklich byte für byte an den PC. Nun habe ich diesen 
Code im Netz gefunden, der für eine struct funktioniert. Allerdings 
nicht, wenn ich eine struct innerhalb einer struct habe -> wie eben 
aktWerte.MotorA ist.
1
/// <summary>
2
        /// Kopiert Daten aus einem Byte-Array in eine entsprechende Strukture (struct). Die Struktur muss ein sequenzeilles Layout besitzen. ( [StructLayout(LayoutKind.Sequential)] 
3
        /// </summary>
4
        /// <param name="array">Das Byte-Array das die daten enthält</param>
5
        /// <param name="offset">Offset ab dem die Daten in die Struktur kopiert werden sollen.</param>
6
        /// <param name="structType">System.Type der Struktur</param>
7
        /// <returns></returns>
8
        static object ByteArrayToStruct(byte[] array, int offset, Type structType)
9
        {
10
            if (structType.StructLayoutAttribute.Value != LayoutKind.Sequential)
11
                throw new ArgumentException("structType ist keine Struktur oder nicht Sequentiell.");
12

13
            //int size = Marshal.SizeOf(structType);
14
            int size = structType.StructLayoutAttribute.Size;
15
            if (array.Length < (offset + size))
16
                throw new ArgumentException("Byte-Array hat die falsche Länge.");
17

18
            byte[] tmp = new byte[size];
19
            Array.Copy(array, offset, tmp, 0, size);
20

21
            GCHandle structHandle = GCHandle.Alloc(tmp, GCHandleType.Pinned);
22
            object structure = Marshal.PtrToStructure(structHandle.AddrOfPinnedObject(), structType);
23
            structHandle.Free();
24

25
            return structure;
26
        }

So übergebe ich meinen Empfangsbuffer (Byte-Array) an die Funktion
1
aktWerte = (werte)ByteArrayToStruct(rx_data, 4+2, typeof(aktWerte));

Die Temperatur, also das Byte gleich am Anfang der struct, funktioniert 
einwandfrei. Innerhalb von aktWerte.MotorA stehen dann die Werte vom PIC 
irgendwo in der struct.
Vielleicht weiß ja jemand von Euch Rat.

Liebe Grüße,
Roblue
#2956779
Lesenswert?
• ▲
▼
Roblue schrieb:
> aktWerte = (werte)ByteArrayToStruct(rx_data, 4+2, typeof(aktWerte));
"aktWerte" ist kein Typ, kann also demzufolge nicht mit dem 
typeof-Operator aufgerufen werden.
1
aktWerte = (werte)ByteArrayToStruct(rx_data, 4 + 2, typeof(werte));

Roblue schrieb:
> [StructLayout(LayoutKind.Sequential, Size = 56)]
> public struct werte
> {
>    public SByte Temperatur;
>    public StepperMotor MotorA;
> };

Wie hast du "StepperMotor" deklariert?
Gast #2957274
Lesenswert?
• ▲
▼
Danke, den Fehler mit dem Typ hab ich beim schreiben des Codes im 
Posting gemacht. In der Software ist das natürlich der Typ "werte".
Inzwischen bin ich etwas schlauer geworden, bzw. funktioniert die 
Übergabe der Werte nun korrekt.
1
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]

Das Pack = 1 macht den Unterschied. Nun steht alles dort, wo es hin 
gehört. Durch einen anderen Thread bin ich drauf gekommen, was das Pack 
eigentlich macht. Mit dieser Angabe muss ich nun auch nicht mehr das 
"size" Attribut manuell festlegen. Die Größe stimmt nun auch mit 
Marshal.SizeOf.

Vielen Dank für Eure Hilfe!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren