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 :

[gSoap] Envoyer un stl::vector ou un array multidimensionnel par gSoap


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2009
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme

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

    Informations forums :
    Inscription : Janvier 2009
    Messages : 23
    Par défaut [gSoap] Envoyer un stl::vector ou un array multidimensionnel par gSoap
    Bonjour à tous.

    J'ai une fonction webservice codée en PHP, recevant un tableau de tableaux de string, et l'écrivant dans un fichier.

    Le WSDL est le suivant :

    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
     
    This XML file does not appear to have any style information associated with it. The document tree is shown below.
    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="ADRESSE_WEBSERVICE" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="BoWS" targetNamespace="ADRESSE_WEBSERVICE">
    <types>
    <xsd:schema targetNamespace="ADRESSE_WEBSERVICE"/>
    </types>
    <portType name="BoWSPort">
    <operation name="writeArray">
    <documentation>This method count and write an array</documentation>
    <input message="tns:writeArrayIn"/>
    <output message="tns:writeArrayOut"/>
    </operation>
    </portType>
    <binding name="BoWSBinding" type="tns:BoWSPort">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="writeArray">
    <soap:operation soapAction="ADRESSE_WEBSERVICE#writeArray"/>
    <input>
    <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="ADRESSE_WEBSERVICE"/>
    </input>
    <output>
    <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="ADRESSE_WEBSERVICE"/>
    </output>
    </operation>
    </binding>
    <service name="BoWSService">
    <port name="BoWSPort" binding="tns:BoWSBinding">
    <soap:address location="ADRESSE_WEBSERVICE"/>
    </port>
    </service>
    <message name="writeArrayIn">
    <part name="array" type="soap-enc:Array"/>
    </message>
    <message name="writeArrayOut">
    <part name="return" type="xsd:int"/>
    </message>
    </definitions>
    Cette fonction fonctionne très bien lorsque je la teste avec soapUI, en lui envoyant le message suivant :

    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
     
    <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="ADRESSE_WEBSERVICE">
       <soapenv:Header/>
       <soapenv:Body>
          <wsdl:writeArray soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
             <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[][3]">
       <SOAP-ENC:Array id="array-1" SOAP-ENC:arrayType="xsd:string[4]">
       	<item>26</item>
       	<item>223</item>
      	<item>test</item>
    	<item>test3</item>
    	</SOAP-ENC:Array>
       <SOAP-ENC:Array id="array-2" SOAP-ENC:arrayType="xsd:string[4]">
       	<item>26</item>
       	<item>750</item>
      	<item>test</item>
    	<item>test4</item>
    	</SOAP-ENC:Array>
    	<SOAP-ENC:Array id="array-3" SOAP-ENC:arrayType="xsd:string[4]">
       	<item>70</item>
       	<item>360</item>
      	<item>tes321</item>
    	<item>test23</item>
    	</SOAP-ENC:Array>
    </SOAP-ENC:Array>
          </wsdl:writeArray>
       </soapenv:Body>
    </soapenv:Envelope>
    Je dois insérer dans cette fonction un tableau multidimensionnel de string depuis un programme en C++.

    J'ai géneré les fonctions et headers gSoap à partir de wsdl2h.

    Le paramètre array de cette fonction est défini de la manière suivante dans le fichier soapStub.h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct _Struct_3
    {
    public:
    	char **__ptr;
    	int __size;
    };
    Mon problème est que je ne sait pas du tout utiliser ce type de structure.

    Le tableau que je dois insérer est à l'origine un vecteur de vecteurs de strings :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector< vector<string> > testArray
    Que je peux facilement transformer en tableau de tableaux de strings.

    Néanmoins, je suis ensuite bloqué.

    Merci d'avance de votre aide.

    Cordialement,

    Niusha.

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Pourrais-tu nous dire ce qui te bloque exactement? Pour avoir une chaîne C-style depuis une std::string: c_str().
    Tu devrais sans doute wrapper le struct dans une classe qui gère cette conversion et la durée de vies des données.
    char** est un tableau de string C-style (tableau de pointeurs sur char). Je suppose que size désigne la taille du tableau.
    Logiquement ton objet-valeur dérivé du struct devrait être un objet local à la fonction.

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2009
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme

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

    Informations forums :
    Inscription : Janvier 2009
    Messages : 23
    Par défaut
    Bonjour et merci pour ta réponse.

    J'ai enfin réussi à remplir mon array.__ptr[i] avec l'ensemble des valeurs de mon vector <vector> string de cette facon :

    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
     
            vector< vector<string> > bounces = pop3.getBounces(); 
     
            _Struct_1 array;
     
            int taille1 = bounces.size();
     
     
            array.__ptr = (char **)malloc(taille1 * sizeof(*array.__ptr));
            if(array.__ptr == NULL)
            {
                //Traitement de l'erreur et fin du programme
            }
     
            int k = 0;
     
            for (int i = 0; i < taille1; i++)
            {
                int taille2 = bounces[i].size();
     
                for (int j = 0; j < taille2; j++)
                {
                    int taille3 = bounces[i][j].size();
     
                    cout << "bounce[" << i << "][" << j << "] = " << bounces[i][j] << endl;
     
                    array.__ptr[k] = (char *)malloc(taille3 + 1);
     
                    if(array.__ptr[k] == NULL)
                    {       
                         //Traitement de l'erreur et fin du programme
                    }
     
                    const char* bounceStr = bounces[i][j].c_str();
                    const char* bounceEncoded = utf8_encode(bounceStr);
                    strcpy(array.__ptr[k], bounceEncoded);
     
                    cout << "array.__ptr[3] = " << array.__ptr[3] << endl; // Pour le test à l'éxecution
     
                    k++;
                }
     
            }
     
            array.__size = taille1 * bounces[0].size();
    Cependant j'ai maintenant un problème d'allocation dynamique mémoire.

    J'alloue de la mémoire pour mon tableau array.__ptr via la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array.__ptr = (char **)malloc(taille1 * sizeof(*array.__ptr)); // taille1 = bounces.size()
    Pour chaque sous éléments de mon vector, j'alloue de la mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array.__ptr[k] = (char *)malloc(taille3 + 1); //(taille3 = bounces[i][j].size()
    .

    Mon array.__ptr[i] se remplis parfaitement de chaques éléments de bounces[i][j], jusqu'à ce que j'arrive à bounces[13][0].

    A ce moment là, la valeur contenue dans array.__ptr[3] est corrompue, alors que tout le reste de ce tableau est correct.

    Voici ce que cela donne à l'éxecution pour le passage où array.__ptr[3] est "corrompu" :

    array.__ptr[3] = recipient rejected (in reply to RCPT TO command)
    bounce[12][3] = recipient rejected (in reply to RCPT TO command)
    array.__ptr[3] = recipient rejected (in reply to RCPT TO command)
    bounce[13][0] = 26
    array.__ptr[3] = À_ž
    bounce[13][1] = 550
    array.__ptr[3] = À_ž

  4. #4
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Euh ... Ma réponse n'aura sûrement aucun rapport avec ton problème, mais ...
    Les noms commençant par __ et par _[majuscule], comme tes __ptr et _Struct_1, sont des identifiants invalides.
    En gros, tu risques de tout faire planter sans raison - et c'est peut-être même ce qui t'arrive actuellement.
    Du coup, commencer par revoir ce nommage serait une bonne idée.

    Et, au passage (bis), les malloc sont remplacés par l'opérateur new en c++.

  5. #5
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2009
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme

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

    Informations forums :
    Inscription : Janvier 2009
    Messages : 23
    Par défaut
    Citation Envoyé par Ekleog Voir le message
    Euh ... Ma réponse n'aura sûrement aucun rapport avec ton problème, mais ...
    Les noms commençant par __ et par _[majuscule], comme tes __ptr et _Struct_1, sont des identifiants invalides.
    En gros, tu risques de tout faire planter sans raison - et c'est peut-être même ce qui t'arrive actuellement.
    Du coup, commencer par revoir ce nommage serait une bonne idée.

    Et, au passage (bis), les malloc sont remplacés par l'opérateur new en c++.
    Merci pour ta réponse.

    Les noms commencant par __ ont été automatiquement génerés par gSoap, qui a pris en compte que la génération était pour du c++ (on peut lui spécifier C ou C++)

    Ensuite, concernant les malloc / new, il me semble que la différence (entre autres sans doutes) est que new prends en compte la destruction d'un objet (pour la programmation en c++), mais que de toutes manières un appel de new engendre un appel de malloc.

    Enfin, j'ai trouvé l'erreur, et mon programme fonctionne maintenant sans erreur :

    La taille de mon array.__ptr était mal calculée.

    Première correction est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int taille1 = bounces.size()*bounces[0].size();
    Ensuite, j'arrêtais ma boucle for si i < taille1, donc cela provoquais un crash puisque i = bounce.size et non pas bounce.size * bounce[0].size (même taille pour tout les bounce[i]), donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int k = 0;
    for (int i = 0; k < taille1; i++)
    Et cela marche correctement !

    Bonne journée !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme avec la STL(vector) avec code C
    Par Benjy dans le forum SL & STL
    Réponses: 12
    Dernier message: 06/04/2006, 12h54
  2. Probleme avec parcours de stl::vector
    Par MDiabolo dans le forum SL & STL
    Réponses: 10
    Dernier message: 08/03/2006, 00h35
  3. STL vector addition
    Par dj.motte dans le forum SL & STL
    Réponses: 1
    Dernier message: 08/11/2004, 08h25
  4. [STL] vector<string> et appel de fonctions.
    Par guejo dans le forum MFC
    Réponses: 4
    Dernier message: 08/10/2004, 17h36
  5. STL::vector crash a l"execution
    Par sebA dans le forum MFC
    Réponses: 2
    Dernier message: 16/06/2004, 16h36

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