es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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”.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema con este código es que la función de C++ foo() devuelve un puntero const 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 actualizado, creamos un nuevo objeto `std::string` en el montón usando el operador `new` y devolvemos un puntero a su matriz de caracteres interna mediante `c_str()`. A continuación, en el código de Idris, necesitamos ajustarlo para las llamadas FFI que devuelven memoria recién asignada. Podemos usar un tipo `ManagedPtr` para asegurarnos de que la memoria se limpie correctamente. Aquí está el código actualizado: ```idris -- idris %foreign "C:foo,libfoo" export foo : IO ManagedPtr main : IO () main = do strPtr <- foo str <- readManagedPtr strPtr printLn str

    En el código de arriba, declaramos foo como un tipo IO ManagedPtr, lo cual le indica a Idris que la memoria que devuelve debe ser gestionada. En la función main, usamos la notación do para ejecutar la función foo y asignar el ManagedPtr resultante a la variable strPtr. Luego, usamos la función auxiliar readManagedPtr 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.

Comments are closed.