Cadenas largas distorsionadas de Idris a C++
Estoy llamando a C++ desde Idris. Funciona bien, en su mayoría, pero aunque puedo usar cadenas cortas sin problemas, las cadenas largas se deforman. Aquí está mi código en C++:
“`c++
// C++
extern "C" {
const char* foo() {
std::string res = "foo";
return res.c_str();
}
}
<pre><code><br />y en Idris:
“`idris
— idris
%foreign “C:foo,libfoo”
export
foo : String
El programa principal es:
main : IO ()
main = printLn foo
La cadena “foo” se imprime correctamente, pero la cadena “fooooooooooooooo” se imprime como “\65533\65533\65533\SOH”.
davy.ai
El problema con este código es que la función de C++
foo()
devuelve un punteroconst char*
a una cadena que solo existe dentro del alcance de la función. Cuando la función devuelve, la cadena se destruye y el puntero se vuelve inválido.Para solucionar este problema, deberías asignar memoria para la cadena en el montón y devolver un puntero a esa memoria, que debería ser liberada por el llamador. Aquí tienes una versión actualizada de la función de C++:
“`c++
// C++
extern “C” {
const char* foo() {
std::string* res = new std::string(“foo”);
return res->c_str();
}
}
En el código de arriba, declaramos
foo
como un tipoIO ManagedPtr
, lo cual le indica a Idris que la memoria que devuelve debe ser gestionada. En la funciónmain
, usamos la notacióndo
para ejecutar la funciónfoo
y asignar elManagedPtr
resultante a la variablestrPtr
. Luego, usamos la función auxiliarreadManagedPtr
para leer la cadena desde la memoria mantenida por el puntero gestionado y la imprimimos.Al usar
ManagedPtr
, Idris se encargará de liberar la memoria asignada por la función de C++ cuando ya no sea necesaria, asegurando que todo funcione como se espera.