IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Python equivalent en C


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    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
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Que fait cette fonction ? Quel est le contexte ? Peux-tu décrire le cas d'application ?

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    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
    5 189
    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 : 5 189
    Points : 17 141
    Points
    17 141
    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
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    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
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    C'est pour envoyer des requêtes dans un certain protocole à un serveur

  7. #7
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    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
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    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
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    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
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Mais struct c'est juste un ensemble de variable, non ?

  11. #11
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    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 : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    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
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    Par défaut
    Je ne suis pas sur d'avoir compris

  14. #14
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 : 1 565
    Points : 7 648
    Points
    7 648
    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
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    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
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 : 1 565
    Points : 7 648
    Points
    7 648
    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
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    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 : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    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
    Nouveau membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Juin 2014
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loiret (Centre)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 63
    Points : 33
    Points
    33
    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
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 : 1 565
    Points : 7 648
    Points
    7 648
    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