2013-07-30 6 views
5

Utilizzo una lib di C++ esterna che esegue alcune comunicazioni HTTPS e fornisce la risposta del server XML. Su serveride la risposta è codificata tramite ISO-8859-15 e ottengo un valore std::string che rappresenta tale risposta fuori dall'API. Quando lo stampo/lo scrivo in un file, sembra corretto.Codifica dei caratteri C++ durante la conversione da stringa a const char * per l'interfaccia Ruby FFI

std::string e un codice di errore int devono essere passati al chiamante esterno. Così ho tornare entrambi i valori all'interno di una struttura:

extern "C" { 
    struct FoobarResponse { 
    const char* responseText; 
    int returnCode; 
    }; 
} 

Purtroppo devo convertire la risposta std::string in una rappresentazione di stringa const char* C-stile con l'aiuto di std::c_str() prima. Motivo: Il mio chiamante è uno script Ruby che fa uso di Ruby FFI per comunicare con la mia lib C++ e la conversione del tipo interlanguage qui è Ruby :: string -> C :: const char *.

Interessante qui: Se I std::cout la stringa convertita dopo averlo inserito nella struct, è ancora ok.

Il problema: quando si gestisce la risposta del server sul lato Ruby, è rotto. Invece della risposta originale come:

<?xml version="1.0" encoding="ISO-8859-15"?> 
<Foobar xmlns="http://www.foobar.com/2012/XMLSchema"> 
    ... 
</Foobar> 

ricevo una stringa contenente ovviamente i caratteri non stampabili che è sempre rotto all'inizio e alla fine.

?O[ 
l version="1.0" encoding="ISO-8859-15"?> 
<Foobar xmlns="http://www.foobar.com/2012/XMLSchema"> 
</Fo?? 

Infatti la stringa contiene interruzioni di riga, ritorni a capo e schede almeno, forse di più.

Ho provato a :force_encoding la stringa sul lato Ruby come ASCII-8BIT, ISO-8859-15 e UTF-8, nessuna modifica. Ho provato a codificare base64 sul lato C++ prima di inserire la stringa nella struct e nella decodifica base64 sul lato Ruby usando this code, nessuna modifica.

Ho avuto innumerevoli tentativi di convertire la stringa utilizzando Iconv, nessuna modifica.

Ho anche provato a rimuovere i caratteri non stampabili dalla stringa prima di inserirlo nella struttura, ma non ci sono riuscito.

Non ho idea di cosa sta succedendo qui e delle opzioni a corto. Qualcuno può indicarmi la giusta direzione?

saluti Felix

risposta

6

Il valore restituito da c_str() viene distrutto appena il std::string passa nell'ambito. Se si intende passare questo valore allo script, è necessario allocare memoria e copiare la stringa nello spazio appena assegnato. Vedere questo esempio: http://www.cplusplus.com/reference/string/string/c_str/

È inoltre necessario assicurarsi che lo script ruby ​​rilascerà correttamente la memoria.

Penso che questo è ciò che viene spiegato qui: https://github.com/ffi/ffi/wiki/Examples.

Esempio con una struttura passò a Ruby da C: https://github.com/ffi/ffi/wiki/Examples#-structs

+0

non supero le stringhe da C a Ruby. Io uso la struttura di cui sopra. La struct è creata dalla mia libreria C e anche la memoria utilizzata dalla struct viene rilasciata in seguito. Sul lato Ruby rifletto la struttura a cui può accedere. Le stringhe nella struttura sono accessibili. Sono solo malformati. Se la memoria fosse stata distrutta troppo presto, non avrei accesso alla stringa all'interno di Ruby, vero? – GeorgieF

+0

Ma la tua struct contiene un membro 'char *. Dovresti allocare la memoria per questo 'char *' e copiare 'c_str()' in questo spazio appena assegnato. Dovresti anche rilasciare questa memoria PRIMA di rilasciare la memoria per la tua struttura. – fjardon

+2

Avresti accesso alla memoria ma sarebbe pieno di spazzatura. Questo è esattamente ciò che vedi. – fjardon