2016-05-12 1 views
2

Je suis en série un paquet sur XDR mais je ne comprends pas comment fournir un vecteur de chaîne. J'ai ici une petite sérialisation/désérialisation entièrement fonctionnante pour un std::vector de uint64_t. Voici mon code:XDR série de variables longueur de la chaîne

sérialiseur:

#include <stdio.h> 
#include <iostream> 
#include <rpc/rpc.h> 
#include <vector> 
#define MAX_LENGTH_ 100 

int main(void) 
{ 
    XDR xdr; 
    xdrstdio_create(&xdr, stdout, XDR_ENCODE); 

    std::vector<uint64_t> ids; // vector i want to send 
    ids.push_back(1); 
    ids.push_back(2); 
    ids.push_back(3); 

    // serializing the vector 
    uint64_t *_ids = &ids[0]; 
    uint32_t size = ids.size(); 
    xdr_array(&xdr,(char**)(&_ids), &size, MAX_LENGTH_,sizeof(uint64_t),(xdrproc_t)xdr_u_long); 

    return 1; 
} 

désérialiseur:

#include <stdio.h> 
#include <iostream> 
#include <rpc/rpc.h> 
#include <vector> 
#define MAX_LENGTH_ 100 

int main(void) 
{ 
    XDR xdrs; 
    xdrstdio_create(&xdrs, stdin, XDR_DECODE); 

    uint64_t *ids_ = new uint64_t[MAX_LENGTH_]; 
    uint32_t size; 
    bool status = xdr_array(&xdrs,(char**)(&ids_), &size, MAX_LENGTH_, 
         sizeof(uint64_t), (xdrproc_t)xdr_u_long); 

    std::vector<uint64_t> ids(ids_,ids_+size); 
    for(std::vector<uint64_t>::iterator it = ids.begin(); it != ids.end(); ++it) 
    { 
     std::cout << *it <<std::endl; 
    } 

    return 1; 
} 

Le code suivant fonctionne ... en cours d'exécution ./serializer | ./deserializer i 1 2 3. obtenir Maintenant, je ne sais pas comment gérer avoir à sérialiser std::vector<std::string>. Une chaîne unique fonctionne bien avec xdr_string.

http://linux.die.net/man/3/xdr_array

Toute aide serait très appréciée!

EDIT:

J'ai essayé ce qui suit: sérialiseur:

#include <stdio.h> 
#include <iostream> 
#include <rpc/rpc.h> 
#include <vector> 
#include <algorithm> 
#include <cstring> 


#define MAX_VECTOR_LENGTH_ 100 
#define MAX_STRING_LENGTH_ 50 

char *convert(const std::string & s) 
{ 
    char *pc = new char[s.size()+1]; 
    std::strcpy(pc, s.c_str()); 
    return pc; 
} 

int main(void) 
{ 
    XDR xdr; 
    xdrstdio_create(&xdr, stdout, XDR_ENCODE); 

    std::vector<std::string> messages; // vector i want to send 
    messages.push_back("this is"); 
    messages.push_back("my string"); 
    messages.push_back("vector test"); 

    // transform the vector to c style 
    std::vector<char*> messagesCStyle; 
    std::transform(messages.begin(), messages.end(), std::back_inserter(messagesCStyle), convert); 

    // serializing the vector 
    char **_messages = &messagesCStyle[0]; 
    uint32_t size = messages.size(); 
    xdr_array(&xdr,(char**)(&_messages), &size, MAX_VECTOR_LENGTH_ * MAX_STRING_LENGTH_,sizeof(char),(xdrproc_t)xdr_string); 

    return 1; 
} 

désérialiseur:

#include <stdio.h> 
#include <iostream> 
#include <rpc/rpc.h> 
#include <vector> 

#define MAX_VECTOR_LENGTH_ 100 
#define MAX_STRING_LENGTH_ 50 

int main(void) 
{ 
    XDR xdrs; 
    xdrstdio_create(&xdrs, stdin, XDR_DECODE); 

    std::vector<char*> messagesCStyle_; 
    uint32_t size; 
    bool status = xdr_array(&xdrs,(char**)(&messagesCStyle_), &size, MAX_VECTOR_LENGTH_, 
         MAX_STRING_LENGTH_, (xdrproc_t)xdr_string); 

    for(std::vector<char*>::iterator it = messagesCStyle_.begin(); it != messagesCStyle_.end(); ++it) 
    { 
     std::cout << *it <<std::endl; 
    } 

    return 1; 
} 

Je suis assez sûr que le code de la sérialiseur je s pas mieux, mais au moins, il semble fonctionner. Cependant le désérialiseur ne le fait pas !! Je pense que le problème est lié au fait que je ne sais pas combien de mémoire allouer avant d'appeler le xdr_array. De l'aide?

+0

est-ce pas un XDR C seule spec? Ensuite, pour l'utiliser pour std :: string, vous devrez peut-être extraire une chaîne compatible C avec, par exemple, messages [i] .c_str(). Ou utilisez la sérialisation boost pour éviter de recourir à un vieux C. –

+0

Tout le reste de l'eporject utilise XDR donc je dois m'en tenir à lui! J'ai marqué la question en tant que C mais Michael a retiré mon tag .... – Stefano

+0

J'ai mis à jour la question avec un code complet. – Stefano

Répondre

0

je l'ai fait travailler:

Encoder:

#include <stdio.h> 
#include <iostream> 
#include <rpc/rpc.h> 
#include <vector> 
#include <algorithm> 
#include <cstring> 


#define MAX_VECTOR_LENGTH_ 100 
#define MAX_STRING_LENGTH_ 50 

char *convert(const std::string & s) 
{ 
    char *pc = new char[s.size()+1]; 
    std::strcpy(pc, s.c_str()); 
    return pc; 
} 

int main(void) 
{ 
    XDR xdr; 
    xdrstdio_create(&xdr, stdout, XDR_ENCODE); 

    std::vector<std::string> messages; // vector i want to send 
    messages.push_back("this is"); 
    messages.push_back("my string"); 
    messages.push_back("vector test"); 
    messages.push_back("this is a relatively long string!!!"); 

    // transform the vector to c style 
    std::vector<char*> messagesCStyle; 
    std::transform(messages.begin(), messages.end(), 
     std::back_inserter(messagesCStyle), 
     [](const std::string & s){ 
      char *pc = new char[s.size()+1]; 
      std::strcpy(pc, s.c_str()); 
      return pc; 
     }); 

    // serializing the vector 
    char **_messages = &messagesCStyle[0]; 
    uint32_t size = messages.size(); 
    xdr_array(&xdr,(char**)(&_messages), &size, MAX_VECTOR_LENGTH_ * MAX_STRING_LENGTH_,sizeof(char*),(xdrproc_t)xdr_string); 

    return 1; 
} 

décodeur:

#include <stdio.h> 
#include <iostream> 
#include <rpc/rpc.h> 
#include <vector> 

#define MAX_VECTOR_LENGTH_ 100 
#define MAX_STRING_LENGTH_ 50 

int main(void) 
{ 
    XDR xdrs; 
    uint32_t size; 
    char** buffer = NULL; 

    xdrstdio_create(&xdrs, stdin, XDR_DECODE); 

    bool status = xdr_array(&xdrs, (char**) &buffer, &size, MAX_VECTOR_LENGTH_, 
         sizeof(char*), (xdrproc_t)xdr_string); 

    std::cout << "status: " << status << std::endl;      
    std::cout << "size: " << size << std::endl; 

    std::vector<std::string> stringMessages_(buffer, buffer + size); 

    for(std::vector<std::string>::iterator it = stringMessages_.begin(); it != stringMessages_.end(); ++it) 
    { 
     std::cout << *it <<std::endl; 
    } 

    for (int i = 0; i < size; i++) { 
     free(buffer[i]); 
    } 
    free(buffer); 

    return 1; 
}