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