Hallo Forengemeinde,
Ich bin ein Anfänger in der C# Welt!
Ich habe hier im Forum die Suche und auch Google bemüht eine Lösung für
mein Problem zu kriegen, leider mit bescheidenem Erfolg.
Zu meinem Problem, ich möchte für eine Serielle Kommunikation zwischen
Mikrocontroller und Pc eine Struktur verwenden. Auf der Mikrocontroller
Seite ("C")kann ich einfach mittels Zeiger die Struktur byteweise
versenden und auch wieder empfangen. Auf der Pc Seite ("C#") gestaltet
sich das für einen Anfänger schwieriger! Ich habe mehrere Ansätze
versucht folgende Struktur
1
publicstructProtocol
2
{
3
publicbyteadress;
4
publicbytecommand;
5
publicbytelen;
6
publicInt16[]recivebuffer;
7
publicuintRtimeout;
8
publicInt16rec_CRC;
9
};
in ein byte Array zu konvertieren.
hier der erste Ansatz:
1
publicbyte[]ByteArrayFromStruct(objectobj)
2
{
3
intlength=Marshal.SizeOf(obj);
4
byte[]array=newbyte[length];
5
6
IntPtrptr=Marshal.AllocHGlobal(length);
7
Marshal.StructureToPtr(obj,ptr,true);
8
Marshal.Copy(ptr,array,0,length);
9
Marshal.FreeHGlobal(ptr);
10
11
returnarray;
12
}
13
byte[]test=Serial.ByteArrayFromStruct(Proto);
aber sobald in der Struktur ein Array vorkommt funktioniert das Ganze
nicht mehr
der zweite Ansatz
1
publicByte[]TestSerialization(objectobj)
2
{
3
BinaryFormatterformatter=newBinaryFormatter();
4
MemoryStreamstream=newMemoryStream();
5
formatter.Serialize(stream,obj);
6
Byte[]buffer=stream.ToArray();
7
returnbuffer;
8
}
9
byte[]test=Serial.TestSerialization(Proto);
bei diesem Ansatz wird das Array 188 byte lang
Was mach ich Falsch?
Wäre sehr dankbar für Eure Professionelle Hilfe
Gruß
otti
man kann die Struktur auch mit dem BinaryWriter / Reader Elementweise
zusammenbauen oder lesen.
Wenn man die Strukturen verwenden will muss man auf das Alignement
achten, damit legt der Compiler die Variablen auf für den Prozessor
'gerade' Adressen. Das sieht in C# aber nicht schöner aus als das
Elementweise schreiben.
in die Strukutrdeklaration müssen die Attribute
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=1)]
rein damit beim Marshalling die Daten richtig aneinandergepackt werden.
In meiner Struktur sind einige Typen als Beispiel drin, komplizierter
sind Arrays in Strukturen weil die ja intern nicht als einfache
Bytearrays abgelegt werden. Und das mit dem fixed Pointer war auch
nötig, weiss grad nicht warum.
Aber wie gesagt, einfacher ist eigentlich die BinaryWriter Klasse zu
verwenden. Du brauchst einen MemoryStream und kannst dann mit
bw.Write(einByte) in den Stream schreiben.
JojoS schrieb:> komplizierter> sind Arrays in Strukturen weil die ja intern nicht als einfache> Bytearrays abgelegt werden.
Genau das ist mein Problem.
Leider brauche ich genau das.
Kann man einen Stream auch in ein byte Array umleiten??
Danke für Deine Hilfe
Gruß
Otti
um den Stream in ein ByteArray zu schreiben hast du ja schon die
richtige Memberfunktion in deinem Beispiel drin:
Byte[] buffer = stream.ToArray();
Um den Stream zu füllen gibts nur die WriteByte() Methode, das ist für
andere Datentypen als Bytes natürlich umständlich, deshalb braucht man
noch den BinaryWriter als Helfer um beliebige andere Daten in den Stream
zu schreiben.
JojoS schrieb:> Um den Stream zu füllen gibts nur die WriteByte() Methode, das ist für> andere Datentypen als Bytes natürlich umständlich, deshalb braucht man> noch den BinaryWriter als Helfer um beliebige andere Daten in den Stream> zu schreiben.
kannst du mir bitte ein kleines Beispiel machen.
Möchte mich für Deine Hilfe schon mal herzlich bedanken!
Gruß
otti
Hi Community,
sorry, dass ich den alten Thread nochmal auskrame.
Wurde zum geposteten Problem mittlerweile eine Lösung gefunden?
Ich hab ein ähnliches Problem. Ich schicke über eine Tcp Verbindung
double und Bytes und empfange diese in einem Array - Buffer.
Nun möchte ich aber auf die einzelnen Einträge des Arrays zugreifen um
diese wieder in einen double oder byte - Wert dekodieren zu können.
Das müsste ich dann auch über einen Struct machen, oder?
Viele Grüße
Sas K. schrieb:> Das müsste ich dann auch über einen Struct machen, oder?
nein, das sollte man nicht mit einer struct machen.
Empfange doch ersmal die byte du die brauchst und wandelst sie dann in
deinen Datentype um.
Bei double z.b
BitConverter.ToDouble(byte[] value,int startIndex)
BitConverter.GetBytes(Double)
http://msdn.microsoft.com/de-de/library/system.bitconverter.aspx
Hi, gut das hat mittlerweile schonmal geklappt.
Jetzt stehe ich vor dem nächsten Schritt, Daten von meinem C# Progamm
über eine Tcp-Verbindung zu senden. Mache es derzeit über die Socket
klasse mit socket.Send.
Problem dabei ist, dass ich nicht nur byte sondern auch double versenden
will und diese vor dem Versenden ja zunächst umwandeln muss.
Hab es schon damit probiert:
System.Convert.ToByte(49.678) (also in diesem Beispiel soll die
Doublezahl 49.678 versendet werden).
Auf meiner Empfangsseite kommen aber immer nur "50" an. Also ganze byte
- Werte.
Wie könnte ich das denn eleganter lösen? Evtl erst eine Struct aufbauen
und diese dann komplett in ein Bytearray wandeln?
Sorry, das hatte ich irgendwie überlesen.
Leider gibt er mir da den Fehler aus, das "Eine implizite Konvertierung
vom Typ "byte[]" in "byte" " nicht möglich ist.
Es funktioniert zwar gut, wenn ich mir einfach noch ein weiteres Array
definiere und den Double dann über GetBytes in dieses Array schreibe.
Aber das müsste sich doch auch noch anders lösen lassen, oder?
1
intc=2;
2
intc1=8;
3
byte[]senden=newbyte[c];
4
byte[]senden1=newbyte[c1];
5
sbytes1=-126;
6
byteb1=(byte)s1;
7
byteb2=120;
8
doubled3=17.234;
9
10
senden[0]=b1;
11
senden[1]=b2;
12
senden1=BitConverter.GetBytes(d3);
13
14
socket.Send(senden);
15
socket.Send(senden1);
Nochmals vielen Dank für eure zahlreichen und hilfreichen Antworten!
saku schrieb:> Es funktioniert zwar gut, wenn ich mir einfach noch ein weiteres Array> definiere und den Double dann über GetBytes in dieses Array schreibe.
GetBytes schreibt nichts in das Array senden1, sondern liefert ein neues
Array zurück, das dann über senden1 "erreichbar" ist (siehe die GetBytes
Typsignatur).
> Aber das müsste sich doch auch noch anders lösen lassen, oder?
s.o. Beitrag von JojoS mit MemoryStream + BinaryWriter
> GetBytes schreibt nichts in das Array senden1, sondern liefert ein neues> Array zurück, das dann über senden1 "erreichbar" ist (siehe die GetBytes> Typsignatur).>
genau, so meinte ich das ja ;) hatte mich vielleicht ein wenig
undeutlich ausgedrückt.
>> s.o. Beitrag von JojoS mit MemoryStream + BinaryWriter
Ok was in diesem Fall doch um einiges umständlicher wäre, als einfach
mehrere Arrays zu senden.
Vielen Dank :)