Gleiche Funktion zum schreiben und lesen in Stream
-
Hi,
ich muss für mein Netzwerkprotokoll die Daten immer wieder in einen buffer (char array) packen und auf der anderen Seite wieder daraus auslesen, etwa so:
Pseudo Code:
void send(char *buffer, int var1, long var2, char var3, int var4) { istringstream stream; // [Makierung] stream << var1 << ","; stream << var2 << ","; stream << var3 << ","; stream << var4 << ","; // [/Makierung] buffer = stream.c_str(); } void receive(char *buffer, int *var1, long *var2, char *var3, int *var4) { char c = 0; // Platzhalter für "," istringstream stream(buffer); // [Makierung] stream >> *var1 >> c; stream >> *var2 >> c; stream >> *var3 >> c; stream >> *var4 >> c; // [/Makierung] }So ist das ganze mal vereinfach ausgedrückt.
Frage:
Wie kann ich die beiden Funktionen zu einer einzigen Funktion zusammenfassen?
Insbesondere stört mich der makierte Teil, den ich gerne durch eine gemeinsame Funktion ersetzen würde.MfG
Scarabol
-
1. das ist keine spiele/graphik frage
2. normalerweise macht man das sovoid Serialize(Serializer& rSerializer) { rSerializer.Data(myVar1); rSerializer.Data(myVar2); rSerializer.Data(myVar3); rSerializer.Data(myVar4); } void send(char *buffer) { Writer W; Serialize(W); buffer = W.c_str(); } void receive(char *buffer) { Reader R(buffer); Serialize(R); }noch besser waere es wenn du einfach beim initializieren der objekte in einen generischen container z.b.
typedef std::vector<std::pair<void*,size_t> > PropertyVec;regestrierst z.b.
CMyAuto::CMyAuto() { m_PropertyVec.push_back(&m_Color,sizeof(m_Color)); m_PropertyVec.push_back(&m_HP,sizeof(m_HP)); m_PropertyVec.push_back(&m_TopSpeed,sizeof(m_TopSpeed)); }und beim serialisieren dann nur
for(iterator it=m_ProperyVec.begin()... rSerializer.Data(it->first,it->second);so kannst du eine basisklasse zum serialisieren haben und alle anderen leiten nur davon ab und regestrieren ihre eigenschaften.
falls mal eine klasse komplexer ist (z.b. dynamische vectoren enthaelt) kannst du immer noch die interface funktion ueberladen und es entsprechend handlen.
natuerlich geht es noch besser.
- du kannst xml verwenden und so flexibilitaet beim format habenvoid Serialize(Serializer& rSerializer) { rSerializer.Data("Color",myVar1); rSerializer.Data("HP",myVar2); rSerializer.Data("Speed",myVar3); rSerializer.Data("Aschebaeschecounter",myVar4); }-alle typen bis zum atomaren/primivite kapselt und jedem sein "Serialize" geben
etc.
-
Dieser Thread wurde von Moderator/in rapso aus dem Forum Spiele-/Grafikprogrammierung in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Die Serialize Funktion muss ich aber doch auch selbst schreiben oder?
Gibt es das nicht schon vorgekaut? Dachte das währe ein "Standardproblem"?
Edit:
Hab gerade die CMap Klasse entdeckt...
Google behauptet zwar das das was mit Serialize zu tun hat aber ich bekomm keinen Durchblick...
Kann mir jemand mit der Serialisation weiterhelfen?MfG
Scarabol
-
Scarabol schrieb:
Die Serialize Funktion muss ich aber doch auch selbst schreiben oder?
Gibt es das nicht schon vorgekaut? Dachte das währe ein "Standardproblem"?
Da C++ keine Reflection hat, musst du die einzelnen Member manuell serialisieren. Es gibt nämlich keine Möglichkeit, von einem Objekt die Eigenschaften zu serialisieren, ohne diese zu kennen.
Allerdings helfen dir Bibliotheken wie Boost.Serialization enorm bei dieser Aufgabe.
-
Also brauche ich für jedes Objekt das ich serialisieren möchte eine eigene Funktion?
MfG
Scarabol
-
Für eigene Objekte, ja. Dinge wie
intoderstd::vectorsind schon implementiert.
-
Nexus schrieb:
Für eigene Objekte, ja. Dinge wie
intoderstd::vectorsind schon implementiert.Wo bzw. in welcher Funktion sind diese schon implementiert?
MfG
Scarabol
-
In der Implementierung von Boost.Serialization. Wo genau, weiss ich nicht, das ist aber auch unwichtig.
-
Kann ich den Operator nicht zur Laufzeit überladen?
MfG
Scarabol
-
Drück dich klarer aus. Von welchem Operator sprichst du? Warum willst du diesen überladen? Und wieso erst zur Laufzeit?
-
Mal so eingeworfen: Gibts dazu noch keinen Artikel? Zu boost::serialization? Wäre was tolles :). Sorry für offtopic.
rya.
-
Hi Leute,
ich hab mir jetzt einfach eine neu Klasse erstellt, die einen stringstream kapselt und die beiden Operatoren >> << hat. Bei << wird halt immer noch ein Trennzeichen mit in den String geschrieben und bei >> wird das Trennzeichen in eine Variable ausgelesen, aber sonst nicht weiter beachtet.
Danke für euere Hilfe.
Ich würde gerne Netzwerkpakete definieren, für die ich beispielsweise eine extra Klasse oder ein Struct anlege, sodass ich bei gemeinsamer Verwendung auf der Client und der Server Seite immer die gleichen Pakete habe.
Was ich bisher weiß ist, dass ich dann für jedes Paket eine eigene serialize() Funktion schreiben müsste in der nur wieder alle Variablen der Klasse aufgelistet sind und die dann hintereinanderweg in einen stringstream geschrieben werden. Gibt es eine Möglichkeit diesen Schritt zu umgehen, dass die Klasse selbsttätig alle ihre Member in einen stream schreibt, oder andere Methoden, oder Ideen?MfG
Scarabol
-
Scarabol schrieb:
void send(char *buffer, int var1, long var2, char var3, int var4) { istringstream stream; // [Makierung] stream << var1 << ","; stream << var2 << ","; stream << var3 << ","; stream << var4 << ","; // [/Makierung] buffer = stream.c_str(); }Also diese Funktion macht ja mal so gar nicht, was du willst. Zuerst mal hat ein istringstream keinen operator<<, du willst einen ostringstream oder einfach einen stringstream. Dann hat stringstream keine Methode c_str(), sondern nur str(), also willst du eher ein stream.str().c_str() (das kann man unter die Kategorie Pseudocode fallen lassen). Das funktioniert aber auch nicht, weil c_str() einen const char* zurückgibt, keinen char*. Selbst wenn diese Zuweisung klappen würde, würde der Code immer noch nicht das von dir gewünschte Verhalten zeigen, weil du den Zeiger buffer per value und nicht per reference überweist, d. h. von der letzten Zuweisung bekommt außerhalb der Funktion keiner was mit. Selbst wenn du den Zeiger per reference übergeben würdest, wäre das Verhalten des Codes höchstwahrscheinlich undefiniert, weil stream beim Verlassen der Funktion zerstört wird.