Pregunta Codificación de caracteres C ++ al convertir de cadena a const char * para la interfaz Ruby FFI


Estoy usando una versión externa de C ++ lib que hace alguna comunicación HTTPS y proporciona la respuesta del servidor XML. En el servidor, la respuesta se codifica a través de ISO-8859-15 y me sale un std::string Eso representa esa respuesta fuera de la API. Cuando lo imprimo / lo escribo en un archivo parece apropiado.

los std::string y un int el código de error debe pasarse a mi interlocutor externo. Así que devuelvo ambos valores dentro de una estructura:

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

Lamentablemente tengo que convertir el std::string respuesta en una const char* Representación de cuerdas estilo C con ayuda de std::c_str() antes de. Motivo: Mi interlocutor es un script de Ruby que utiliza Ruby FFI para comunicarse con mi C ++ lib, y aquí la conversión de tipo de interlenguaje es Ruby :: string -> C :: const char *.

Interesante aquí: si yo std::cout la cadena convertida después de que la puse en la estructura, todavía está bien.

El problema: cuando se maneja la respuesta del servidor en el lado de Ruby, se rompe. En lugar de la respuesta original como:

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

Recibo una cadena que obviamente contiene caracteres no imprimibles que siempre se rompen al principio y al final.

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

De hecho, la cadena contiene saltos de línea, retornos de carro y pestañas al menos, tal vez más.

lo intenté :force_encoding la cadena en el lado de rubí como ASCII-8BIT, ISO-8859-15 y UTF-8, ningún cambio. Intenté codificar en base64 en el lado C ++ antes de colocar la cadena en la estructura y decodificar en base64 en el lado Ruby usando este código, ningún cambio.

Tuve innumerables intentos para convertir la cadena usando Iconv así, no hay cambio.

También traté de eliminar los caracteres no imprimibles de la cadena antes de ponerlos en la estructura, pero fallé en eso.

No tengo idea de lo que está pasando aquí y quedándome sin opciones. ¿Puede alguien apuntarme en la dirección correcta?

Saludos Felix


5
2017-07-30 09:10


origen


Respuestas:


El valor devuelto por c_str() se destruye tan pronto como el std::string sale del alcance. Si tiene la intención de pasar este valor a su secuencia de comandos, debe asignar memoria y copiar la cadena en su espacio recientemente asignado. Vea este ejemplo: http://www.cplusplus.com/reference/string/string/c_str/

También debes asegurarte de que el script ruby ​​libere correctamente la memoria.

Creo que esto es lo que se explica allí: https://github.com/ffi/ffi/wiki/Examples.

Ejemplo con una estructura pasada a Ruby desde C: https://github.com/ffi/ffi/wiki/Examples#-structs


7
2017-07-30 09:59