1. #1
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut Python equivalent en C

    Bonjour,
    J'ai un programme python qu utilise la fonction pack du module struct. Et j'aimerais avoir son équivalent en langage C.
    Merci

  2. #2
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    1 011
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 011
    Points : 2 977
    Points
    2 977

    Par défaut

    Que fait cette fonction ? Quel est le contexte ? Peux-tu décrire le cas d'application ?

  3. #3
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    Bonjour,
    Merci pour ta réponse.
    Je ne connais pas trop python, mais elle à l'air d'être utilisé pour "formater" des chaines de caractères.
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x += pack("B",l & 0x7F)
    où l est un entier.
    A chaque fois qu'elle est utilisé, c'est pour des chaines de caractères.

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    4 757
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : juin 2007
    Messages : 4 757
    Points : 15 442
    Points
    15 442

    Par défaut

    Si j'en crois la documentation (2.7 ou 3.6), struct permet la conversion string <-> octets.
    struct.pack(fmt, v1, v2, ...)
        Return a string containing the values v1, v2, ... packed according to the given format. The arguments must match the values required by the format exactly
    Ca ressemble terriblement à sprintf(output_buffer, "format", v1, v2, ...).
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    1 011
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 011
    Points : 2 977
    Points
    2 977

    Par défaut

    Ok, cette fonction produit une séquence d'octets qui peut être affectée à un enregistrement C défini avec l'arrangement correspondant. Il n'y a pas lieu d'y avoir d'équivalent puisque cette fonction est justement destinée à l'interopérabilité vers C. L'équivalent c'est une struct compatible avec le format décrit.

    Je pose donc à nouveau la question :

    Citation Envoyé par Matt_Houston Voir le message
    Peux-tu décrire le cas d'application ?

  6. #6
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    C'est pour envoyer des requêtes dans un certain protocole à un serveur

  7. #7
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    1 011
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 011
    Points : 2 977
    Points
    2 977

    Par défaut

    Certes mais dans quel cadre, comment ça se passe ? Que cherches-tu à faire en C qui nécessite cette opération ? Où est le programme C ? Où est le script Python ? Comment doivent-ils communiquer ?

  8. #8
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    Voilà le script python que j'aimerais traduire en C :
    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
     
    TYPE_ENUM = 0
    TYPE_STRING = 2
    TYPE_BYTES = 2
    protocolVersion = 0
    source_id = "sender"
    destination_id = "receiver"
    server = "10.2.182.26"
    namespace = "urn:dial-multiscreen-org:service:dial:1"
    data = "{\"type\":\"GET CONNECTION\",\"origin\":{}}"
    lnData = getLenOf(data)
     
    socket = socket.socket()
    socket = ssl.wrap_socket(socket)
    socket.connect((server,1900))
     
    msg = pack(">BBBB%dsBB%dsBB%dsBBB%ds%ds" % (len(source_id),len(destination_id),len(namespace),len(lnData),len(data)),getType(1,TYPE_ENUM),protocolVersion,getType(2,TYPE_STRING),len(source_id),source_id,getType(3,TYPE_STRING),len(destination_id),destination_id,getType(4,TYPE_STRING),len(namespace),namespace,getType(5,TYPE_ENUM),0,getType(6,TYPE_BYTES),lnData,data)
     
    msg = pack(">I%ds" % (len(msg)),len(msg),msg)
     
    socket.write(msg)
    Et la fonction getLenOf :
    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

  9. #9
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    1 011
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 011
    Points : 2 977
    Points
    2 977

    Par défaut

    Il te suffit de mettre tous ces champs dans un enregistrement (struct) et de :

    • l'envoyer tel quel si les chaînes sont stockées dans des buffers de taille fixe ;
    • écrire une fonction qui le sérialise vers un flux si les chaînes sont de longueur variable.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    Mais struct c'est juste un ensemble de variable, non ?

  11. #11
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    1 011
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 011
    Points : 2 977
    Points
    2 977

    Par défaut

    Oui.. et ? C'est justement ce que fait pack : concaténer une séquence de données telle qu'elle serait arrangée en C.

  12. #12
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : janvier 2014
    Messages : 539
    Points : 2 598
    Points
    2 598

    Par défaut

    faut juste faire attention au padding, et en général pour ce genre de truc on l'inhibe pour avoir la main sur le formatage des données (pragma ou attributes en gcc/clang).

  13. #13
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    Je ne suis pas sur d'avoir compris

  14. #14
    Membre émérite
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 477
    Points : 2 262
    Points
    2 262

    Par défaut

    Le but est de remplir un buffer d'octets dans un format donné. On peut définir une fonction pour les 3 types de pack (B,%ds et I) et les utiliser pour remplir le buffer
    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
    unsigned pack_B( uint8_t* buf , unsigned offset , uint8_t v ) {
       buf[offset] = v;
       return offset+1;
    }
    unsigned pack_pct_ds( uint8_t* buf , unsigned offset, char const *v ) {
       size_t lg = strlen( v );
       memcpy( buf + offset , v , lg );
       return offset + lg;
    }
    unsigned pack_I( uint8_t* buf , unsigned offset , uint32_t v ) {
       buf[offset] = v >> 24;
       buf[offset + 1] = 0xff & (v >> 16);
       buf[offset + 2] = 0xff & (v >> 8);
       buf[offset + 3] = 0xff & v;
       return offset + 4;
    }
    void do_it() {
       uint8_t buffer[4096];
       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) );
       offset = pack_pct_ds( buffer , offset , source_id );
       ... ...
       offset += pack_I( buffer , 0 , offset );
       send( socket, buffer , offset, 0);
    }

  15. #15
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    Du coup, j'ai ça :
    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
       uint8_t buffer[4096];
       unsigned offset = 4; // reserver 4 octets pour le pack("I") fait en dernier
       offset = pack_B( buffer , offset , strlen(source_id) );
       offset = pack_B( buffer , offset , strlen(destination_id) );
       offset = pack_B( buffer , offset , strlen(namespace) );
       offset = pack_B( buffer , offset , 1 );
       offset = pack_B( buffer , offset , strlen(data) );
       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) );
       offset = pack_pct_ds( buffer , offset , source_id );
       offset = pack_B( buffer , offset , getType(3, TYPE_STRING) );
       offset = pack_B( buffer , offset , strlen(destination_id) );
       offset = pack_pct_ds( buffer , offset , destination_id );
       offset = pack_B( buffer , offset , getType(4, TYPE_STRING) );
       offset = pack_B( buffer , offset , strlen(namespace) );
       offset = pack_pct_ds( buffer , offset , namespace );
       offset = pack_B( buffer , offset , getType(5, TYPE_ENUM) );
       offset = pack_B( buffer , offset , payloadType );
       offset = pack_B( buffer , offset , getType(6, TYPE_ENUM) );
       offset = pack_B( buffer , offset , getLenOf(data) );
       offset = pack_pct_ds( buffer , offset , namespace );
     
       offset += pack_I( buffer , 0 , offset );
       send(sock, buffer , offset, 0);
    Bon, ben quand j'envoie au serveur, je ne reçoit rien.
    Le script python avat aussi une socket sécurisé avec socket_wrap.
    Est-ce qu'il est nécessaire en C que ma socket soit sécurisé ?

  16. #16
    Membre émérite
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 477
    Points : 2 262
    Points
    2 262

    Par défaut

    Ta séquence de pack n'est pas bonne, les données passées en % n'ont pas être traitées (elle fournissent la longueurs des %ds dans le format mais ne sont pas dans le buffer). Il doit y avoir exactement le même nombre d'appels que de "B" "%ds" et "I" que dans le format, j'ai indiqué les 5 premiers. Et attention au lnData qui doit être calculé et transmis sous la forme d'une chaîne.
    Si le socket était sécurisé, il y a de forte chance que tu nécessites de faire de même.

  17. #17
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    Mais à quoi correspond %ds ?
    Les B c'est pour unsigned char, I pour unsigned int...

    Mais là on les copie dans le buffer les %ds, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy( buf + offset , v , lg );

  18. #18
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : janvier 2014
    Messages : 539
    Points : 2 598
    Points
    2 598

    Par défaut

    Si tu dois envoyer dans cet ordre un byte, un short (16bit), deux bytes, un int (32bits) alors tu fais une structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct foo {
        unsigned char first_byte ;
        short first_short;
        unsigned char second_byte;
        unsigned char third_byte;
        int last_int;
    } __attribute__ (( packed ));
    Tu la remplis, tu l'écris avec un write (attention à l'endianness) et basta.
    J'ai présenté la syntaxe d'attribut valide avec gcc/clang, mais on peut aussi un pragma.

  19. #19
    Membre à l'essai
    Homme Profil pro
    Etudiant
    Inscrit en
    juin 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2014
    Messages : 45
    Points : 22
    Points
    22

    Par défaut

    Je suis pas obligé d'utiliser send pour envoyer un flux de données sur le réseau ?
    Donc c'est un peu comme pour écrire dans un fichier en mode binaire, sauf qu'on utilise write au lieu de fwrite, comme le montre cet exemple ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    typedef struct {
     
         int age;
         char nom[30];
         char prenom[30];
         char adresse[60];
         int nombreFreres;
     
    }SPersonne ;
     
    SPersonne personne;  //Je déclare une variable de type SPersonne
    fwrite( &personne , sizeof(personne) , 1 , fichier);

  20. #20
    Membre émérite
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 477
    Points : 2 262
    Points
    2 262

    Par défaut

    Citation Envoyé par AchilleFraisse Voir le message
    Mais là on les copie dans le buffer les %ds, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy( buf + offset , v , lg );
    Quand on fait pack( "%ds" %(len(str)) , str ) pour une chaîne str de 12 caractères, c'est équivalent à pack( "12s" , str ), ça met donc dans le buffer tous les caractères de la chaîne.

Discussions similaires

  1. Equivalent de "PAUSE" en Python ?
    Par Lenezir dans le forum Général Python
    Réponses: 12
    Dernier message: 16/08/2011, 11h05
  2. Equivalent sort -u unix en python
    Par AnsuzPeorth dans le forum Général Python
    Réponses: 7
    Dernier message: 13/03/2010, 18h37
  3. Réponses: 3
    Dernier message: 03/07/2009, 09h58
  4. [WxRuby] Equivalent python de CheckListCTRL
    Par Jeremy0201 dans le forum Ruby
    Réponses: 0
    Dernier message: 09/01/2009, 12h05
  5. Equivalent à sleep en python
    Par breakwall dans le forum Général Python
    Réponses: 3
    Dernier message: 09/10/2008, 15h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo