Donc on doit bien faire appel à pack_B pour le len et pack_pct_ds pour le char*, non ?
Donc on doit bien faire appel à pack_B pour le len et pack_pct_ds pour le char*, non ?
Vous vous rendez compte du problème XY ?
On a au départ un truc certainement écrit en qui utilise des structures. Ensuite on passe en pyhton qui ne propose pas le même type natif mais passe par un module externe pour créer ces structures C. On revient en C ensuite et on essaye d'initer le comportement du module python … et du coup on fait un truc tout compliqué !
C'est pas un peu le serpent qui se tire une balle dans le pied ça ?
Bon, j'ai essayé de faire comme tu as dit piceodev.
Est-ce qu'on obtient ça du coup ?
Puis l'envoie :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 typedef struct { unsigned char lensourceid1; unsigned char lendestinationid1; unsigned char lennamespace1; unsigned char lenlndata; unsigned char lendata; unsigned char gettypeenum1; unsigned char protocolVersion; unsigned char gettypestring1; unsigned char len_sourceid2; char *sourceid; unsigned char gettypestring2; unsigned char lendestinationid2; char *destination; unsigned char gettypestring3; unsigned char lennamespace2; char *namespace; unsigned char gettypeenum2; unsigned char payloadtype; unsigned char gettypebytes; unsigned char lndata; char *data; } Request; Request req1; req1.lensourceid1 = strlen(source_id); req1.lendestinationid1 = strlen(destination_id); req1.lennamespace1 = strlen(namespace); req1.lenlndata = 1; req1.lendata = strlen(data); req1.gettypeenum1 = getType(1, TYPE_ENUM); req1.protocolVersion = protocolVersion; req1.gettypestring1 = getType(2, TYPE_STRING); req1.len_sourceid2 = strlen(source_id); req1.sourceid = malloc(req1.len_sourceid2); strcpy(req1.sourceid, source_id); req1.gettypestring2 = getType(3, TYPE_STRING); req1.lendestinationid2 = strlen(destination_id); req1.destination = malloc(req1.lendestinationid2); strcpy(req1.destination, destination_id); req1.gettypestring3 = getType(4, TYPE_STRING); req1.lennamespace2 = strlen(namespace); req1.namespace = malloc(req1.lennamespace2); strcpy(req1.namespace, namespace); req1.gettypeenum2 = getType(5, TYPE_ENUM); req1.payloadtype = payloadtype; req1.gettypebytes = getType(6, TYPE_BYTES); req1.lndata = strlen(data); req1.data = malloc(req1.lndata); strcpy(req1.data, data);
Code : Sélectionner tout - Visualiser dans une fenêtre à part write(sock, &req1, sizeof req1);
@AchilleFraise, On te donne deux moyens différents pour atteindre ton objectif. Tu sembles un peu perdu entre les possibilités. Il faut à la fois bien suivre la partie Python et bien comprendre le code C que tu génères.
Pour la méthode par structure, selon moi elle a des pièges (ainsi tu y a mis des pointeurs et en aucun cas ça n'a de sens de transmettre un pointeur à une entité externe), il y des données à longueurs variables dans la trame et cela n'est pas simple à coder en C.
Je t'ai proposé de procéder par écriture dans un buffer (méthode plus génèrale).
Au final le but des deux méthodes est identique, arriver à une zone de mémoire remplie avec les bonnes données au bon format pour la transmettre.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 // Le format ">" indique bigEndian, "B" sont des octets, "%d" spécifie la longueur du "s" msg = pack(">BBBB%dsBB%dsBB%dsBBB%ds%ds" // pour chaque %d du format indique sa longueur (ne correspond à aucune donnée à mettre dans msg!) %(len(source_id),len(destination_id),len(namespace),len(lnData),len(data)), // les données à placer dans la trame(ou la structure) sont indiquées à partir d'ici getType(1,TYPE_ENUM),protocolVersion,getType(2,TYPE_STRING), // correspond à BBB len(source_id),source_id, // correspond à B%ds donc lg sur 1oct et chaîne sur sa lngueur getType(3,TYPE_STRING),len(destination_id),destination_id, // correspond à BB%ds getType(4,TYPE_STRING),len(namespace),namespace, // correspond à BB%ds getType(5,TYPE_ENUM),0,getType(6,TYPE_BYTES), // correspond à BBB lnData, // correspond à %ds, lnData est une chaîne calculée avant data) // correspond à %ds
Donc ca donne ça :
?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 unsigned offset = 4; // reserver 4 octets pour le pack("I") fait en dernier offset = pack_B( buffer , offset , getType(1, TYPE_ENUM) ); offset = pack_B( buffer , offset , protocolVersion ); offset = pack_B( buffer , offset , getType(2, TYPE_STRING) ); offset = pack_B( buffer , offset , strlen(source_id) ); ... send(sock, buffer , offset, 0); }
Personne ?
J'ai 4 octets de trop et le 4 octets n'est pas le bon. Sinon le reste du message va bien
Edit : Pour les 4 octets de trop je pense que c'est à cause du
dans pack_I, car on a déjà compté les 4 dans l'offset de départ. Mais pour le 4e octet du message qui n'est pas le bon ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part return offset + 4
Désolé, c'est plutôt le += de la fin que je t'ai indiqué qui doit être enlevé (sinon compte 2 fois ces 4 octets.)
Et pour cette fonction :
J'ai fais ça :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 def getLenOf(s): x = "" l = len(s) while(l > 0x7F): x += pack("B",l & 0x7F | 0x80) l >>= 7 x += pack("B",l & 0x7F) return x
, mais ce ne marche pas
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 uint8_t *getLenOfBis(const char *s) { uint8_t *x; int len = strlen(s); int offset = 0; x = malloc(3); x[0] = 0; x[1] = 0; x[2] = 0; while(len > 0x7F) { offset=pack_B(x, offset, len&0x7F|0x80); len >>=7; } offset = pack_B(x, offset, len&0x7F); printf("%s\t%d\n", x, offset); return x; }
Bonjour
Déjà moi le malloc je lui demanderais d'allouer 3 * sizeof uint8_t octets au lieu de seulement 3 octets. Et s'il faut tout remplir ensuite de 0 ben on peut aussi alors se tourner alors vers memset ou faire un pack complet via calloc mais bon, le faire à la main ça marche aussi surtout que j'ai lu une fois dans ce forum une intéressante discussion où l'auteur disait que tout remplir une variable de 0 binaire ne garantit pas la valeur "0" à l'arrivée parce que rien n'oblige "0" à être codé "0x0000").
Mais surtout dans le code Python il y a un x qui est initialisé puis qui est ensuite modifié via le x += .... Or dans le code C, je ne vois rien d'analogue. Ce que renvoie la fonction pack va remplir un "offset" (offset qui est réutilisé à l'itération suivante) mais ne semble pas toucher à "x" (sauf que comme c'est un pointeur il est peut-être directement modifié par la fonction comme le montre l'exemple de dalfab). Mais si c'est cela, alors un autre souci c'est que cette boucle pourrait faire bien plus que 3 itérations tandis que "x" n'est prévu que pour 3 items.
Sinon quand tu dis "ce ne marche pas", tu ne pourrais pas être plus clair ? Par exemple tu affiches "x" et "offset" avant de le retourner. Tu n'aurais pas eu en plus l'idée d'afficher x[0], x[1] et x[2] et nous dire "en plus" si le contenu de tout cet affichage était cohérent avec ce que tu attends ??
Et sinon t'as testé de façon individuelle ta fonction pack ??? (remarque ça rejoint ma demande précédente)...
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager