pack/unpack im C/C++
-
Hallöchen,
ich habe ein Problem, welches ich auch durch stundenlanges googeln und kollegen fragen nicht wirklich lösen konnte.
momentan schreibe ich an einem C++ programm, welches über TCP/IP mit einem python programm kommunizieren soll (fragt lieber nicht wieso).
Die grundlagen zum socket-messaging usw sind soweit klar. Kopfschmerzen bereiten mir die funktionen struct.pack() und struct.unpack() aus python.Infos zu diesen Befehlen gibt es hier: http://www.python.org/doc/2.4.1/lib/module-struct.html
Also:
Schicke einen mittels pack() gepackten befehl von python aus los (auf den tcp/ip strom). Mein c++ programm soll diesen nun auslesen und vergleichen (sockets und so schon alles eingebaut). Problem ist dass die Daten gepackt (sprich also binary strings) sind und ich demnach keinen direkten vergleich machen kann ohne diese zu unpacken. Ungepackt kommen die daten natürlich so an, dass ich sie vergleichen kann. Das ist aber nicht der sinn der sache (auch hier lieber nicht fragen warum).Wollte also auf diesem wege fragen ob es in c oder c++ eine äquivalente funktion zum struct.pack() und/oder struct.unpack() aus python gibt.
Gibt ja leider kein python/c++ forum, sonst hätt ich das da gepostet. Hoffe hier kann mir wer helfen.
-
so wie ich das verstehe mit pack() packt das einfach die bytes hinternander. dh. wenn du zB sowas in python machst:
pack('ss', 'test1', 'test2');
Dann denk ich mal, dass folgendes dabei rauskommt:
'test1\0test2\0'
Also bei \0 einfach splitten, wenn du nur strings speicherst. Wenn noch Zahlen drin sind, steht ja auf der Seite, wie die kodiert werden. Scheint doch eigentlich nicht so schwierig zu sein, wenn ich das ales richtig verstanden hab
-
ist leider nicht ganz so einfach. Bei strings mag das noch klappen, jedenfalls modifiziert, da ein s auch nur als ein teil des strings gehandhabt wird
musst das eher so machen:
> struct.pack(5s5s,'test1','test2')
'test1test2'bei mehr als 5 wäre das dann so:
> struct.pack(6s6s,'test1','test2')
'test1\x00test2\x00'was ist aber bei ints (welche ich unter anderen auch benötige):
> struct.pack('i', 3384)
'8\r\x00\x00'sieht das ganze schon etwas kryptischer aus und ergbt für mich keinen richtigen zusammenhang. (ausser dass die "\" scheinbar die bytes unterteilen
-
Der Zusammenhang ist ganz einfach - die binären Daten des int's werden byteweise als Zeichen interpretiert - 3384 == 0xD38 wird offenbar im Big-Endian-Format(?) geschrieben (0x38=='8', 0x0D=='\r', die beiden höchstwertigen Bytes werden mit 0 aufgefüllt).
(in C++ reicht ein reinterpret_cast<char*> oder memcpy() aus, um das zu bewerkstelligen)
-
Unter Python (Modul socket) kann man Daten ausschließlich als strings (wobei Strings keine Zeichenketten als solche sind, sondern Byte-Strings) versenden.
Um interne Datentypen (hier: integer und float) versenden zu können, existiert das Modul struct. Wie in der Referenz(1) beschrieben, kann man hiermit C-Strukturen "zusammenbasteln". In der genannten Referenz findest du auch die einzelnen Formate für die C-Datentypen.
>>> struct.pack('H', 1234) '\xd2\x04'... liefert dir demnach 1234 als unsigned short (zwei Bytes) - Es handelt sich nicht (!) um eine Null-terminierte Zeichenkette.
>>> struct.pack('d', 1234) '\x00\x00\x00\x00\x00H\x93@'... der selbe Wert als double.
Wie CStoll schon anmerkte, müsstest du für den von dir (auf Empfängerseite) geünschten Datentyp entsprechende Bytes (z.B. sizeof(double) ) reservieren und mittels casting in den entsprechenden Datentyp überführen.
M.E. klingt das aber nach einem ziemlichen Gemurkse und du solltest vielleicht deine Befehle mittels eines Eingabestromes abfragen.
Auf Python-Seiten müsstes du dann entsprechend die Zeichenketten durch den Äther jagen (denk an die Encodings, gerade wenn du mit Unicode-Strings arbeitest).
Grüße...
Heiko
-
ok, danke euch erstmal.

werde das mal ausprobieren. Dauert evtl. eine weile. Melde mich dann bei neuen problemen diesbezüglich oder wenn es geklappt hat nochmal.