Velneo, dll’s y cadenas

Cuando trabajamos con Velneo y necesitamos hacer una llamada a una dll que retorna una cadena (string) nos encontramos con la tesitura de como liberar el espacio de memoria alojada para la cadena en cuestión en la dll. Veamos un método, que no el único, para liberar esa memoria. Este método sólo va a servir para las dlls que creemos nosotros, ya que debemos añadir un par de funciones extra.

El escenario

Veamos el escenario que vamos a utilizar para poner en funcionamiento nuestra técnica. Tenemos un mapa en Velneo desde el que necesitamos llamar a una función de una dll que debe retornar una cadena de caracteres (un char*). La cadena no tiene una longitud fija, por lo que nos interesa alojar el espacio en memoria en la propia función de la dll y retornar la cadena completa.

La solución

Lo primero que se nos ocurre es hacer una función que retorne un char* y recogerlo en Velneo, pero tenemos que ser conscientes de que ese espacio en memoria no se a a liberar, por lo que estamos dejando un motón de basura.

Lo que vamos a hacer es retornar el puntero a ese char*, y nos creamos dos funciones extra en la dll, getString y freeString. El código en C sería algo así:
unsigned long test(int variables, ...)
{
char* cadena = (char *) malloc(1024);
// Procesamos la cadena y retornamos su direccion de memoria
return (unsigned long)cadena;
}


char* getString(unsigned long address)
{ // Retornamos el contenido de esa dirección
return (char*) address;
}


void freeString(unsigned long address)
{ // Liberamos esa dirección de memoria
free((void *)address);
}

Desde Velneo haremos las llamadas en el siguiente orden:

Set ptr_cadena, testDll.test('variables')
// En esta variable local tenemos la direccion de memoria. Obtengamos el contenido
Set cadena, testDll.getString('ptr_cadena')
// Liberemos ese espacio reservado
Set void, testDll.freeString('ptr_cadena')

Con esta sencilla artimaña nos aseguramos de que no quede espacio en memoria ocupada sin liberar.

Esta es la opción que yo utilizo. Si usas algún otro truco, aprovecha para compartirlo con la comunidad escribiendo un comentario.

Anuncios

5 responses to this post.

  1. Si utilizas C++ puedes usar la Clase String para estas lides.

    char* __stdcall Fichero2Cadena(const char* rutaFichero){

    int iFileHandle;
    int iFileLength;
    char *buffer;
    AnsiString strTemp;

    try{
    iFileHandle = FileOpen(rutaFichero, fmOpenRead);
    iFileLength = FileSeek(iFileHandle,0,2);
    FileSeek(iFileHandle,0,0);

    buffer = (char*)malloc((iFileLength+1)*sizeof(char));

    FileRead(iFileHandle, buffer, iFileLength);
    FileClose(iFileHandle);

    // *************************************************************
    // Asignamos a un AnsiString el buffer para así poder liberarlo.
    // *************************************************************
    strTemp = buffer;
    free(buffer);
    return (char*)strTemp.c_str();
    }
    catch(Exception &e){
    free(buffer);
    return (char*)e.Message.c_str();
    }
    }

    Responder

  2. Posted by gVera on 20 junio 2008 at 12:56 pm

    Efectivamente parece un sistema mucho más sencillo. Lo que no tengo tan claro es que la memoria alojada para strTemp sea liberada. Me lo puedes confirmar?

    Responder

  3. Posted by Roberto Blasco on 25 junio 2008 at 11:22 pm

    Hola gVera.

    Ya quisiera yo que mi conocimiento de C/C++ fuera lo suficientemente sólido como para hacer cualquier aseveración a prueba de bombas….

    Por lo que yo sé, el tipo de clase String declarado dentro de una función se libera al terminar ésta.

    Un saludo. Roberto.

    Responder

  4. Posted by admin on 14 noviembre 2009 at 10:34 pm

    Gracias por el artículo. Recientemente hice una DLL para Windev 14 y, a diferencia de velneo que puede recibir el contenido total de un string directamente, Windev solamente puede recibir retornos Int, por lo que obliga a enviar la dirección de una variable a una función y en la DLL reasignar el contenido con apuntadores, pero para que funcione debe preservarse el contenido del string, pues en windev la siguiente línea de código es la obtención del valor por apuntador a una variable local, y ya para finalizar, liberar el contenido de esa variable como bien comentas.

    En poco tiempo implementé ésta última función que necesitaba.

    Saludos cordiales

    Responder

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: