• Domingo 13 de Octubre de 2024, 15:20

Autor Tema:  ¿cómo Cargar Una Dll?  (Leído 2306 veces)

Anonymous

  • Visitante
¿cómo Cargar Una Dll?
« en: Lunes 20 de Noviembre de 2006, 21:49 »
0
Tengo un fichero de cabecera (un .h) en el que se definen una serie de clases con sus métodos. El problema es que en las implementaciones de estos métodos se utilzan funciones que están implementadas en una DLL y por lo tanto necesito cargar la DLL para que el compilador pueda linkear el código fuente con las funciones y generar el ejecutable.

No sé cómo hacer esto, cuando compilo no me da ningún error de sintaxis pero sí me dan unos cuantos errores de linkeo.

Si alguien pudiera ayudarme estaría eternamente agredecido.

Saludos a todos.    :hola:

Anonymous

  • Visitante
Re: ¿cómo Cargar Una Dll?
« Respuesta #1 en: Martes 21 de Noviembre de 2006, 15:26 »
0
Ante todo les pido disculpas por no haber revisado los mensajes del forum.

Hoy me dediqué a buscar y vi que en uno de ellos el moderador de ASM explica que para cargar una DLL se utiliza LoadLibrary. Pero tengo una duda: ¿después de haber cargado la librería en memoria ya podemos hacer uso de sus funciones exportadas como si su código estubiera en nuestra aplicación?, ¿o hay que utilzar "GetProcAddress" para obtener la dirección de sus funciones y después con esas direcciones hacer la llamada?

Saludos a todos.  :hola:

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: ¿cómo Cargar Una Dll?
« Respuesta #2 en: Martes 21 de Noviembre de 2006, 15:39 »
0
Las DLLs no fueron creadas para C++ sino para C y usar enlazado dinamico (LoadLibrary + GetProcAddress) no esta soportado. Lo que podes hacer es intentar conseguir el equivalente de una .lib (libreria de importacion) para usar en Borland y tener enlazado estatico, de esta manera no hace falta LoadLibrary ni GetProcAddress y podes usar clases.

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

Anonymous

  • Visitante
Re: ¿cómo Cargar Una Dll?
« Respuesta #3 en: Martes 21 de Noviembre de 2006, 22:23 »
0
Bueno... Antes de leer tu respuesta probé con LoadLibrary y GetProcAddress y no me dio ningún error. La librería sí se carga pero cuando intento obtener la dirección de una función exportada me dice que no encuentra esa función en la librería.  Lo probé con dos funciones exportadas que tengo en la librería y en las dos dice lo mismo. La primera función exportada la copié de la ayuda del C++ Builder.

Aquí está el código de la librería:

#include <windows.h>
double dblValue(double);
double halfValue(double);
extern "C" __declspec(dllexport) double changeValue(double, bool);

double dblValue(double value)
{
   return value * value;
};
double halfValue(double value)
{
   return value / 2.0;
}
double changeValue(double value, bool whichOp)
{
   return whichOp ? dblValue(value) : halfValue(value);

}


#define EOF (-1)
 
#ifdef __cplusplus    // If used by C++ code,
extern "C" {          // we need to export the C interface
#endif
 
__declspec(dllexport) int myPuts(LPTSTR lpszMsg)
{
    DWORD cchWritten;
    HANDLE hStdout;
    BOOL fRet;
 
    // Get a handle to the standard output device.
 
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if (INVALID_HANDLE_VALUE == hStdout)
        return EOF;
 
    // Write a null-terminated string to the standard output device.
 
    while (*lpszMsg != '\0')
    {
        fRet = WriteFile(hStdout, lpszMsg, 1, &cchWritten, NULL);
        if( (FALSE == fRet) || (1 != cchWritten) )
            return EOF;
        lpszMsg++;
    }
    return 1;
}
 
#ifdef __cplusplus
}
#endif


y ahora el código de la aplicación que llama:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
// A simple program that uses LoadLibrary and
// GetProcAddress to access myPuts from Myputs.dll.
 
#include <stdio.h>
#include <windows.h>
 
typedef int (*MYPROC)(LPTSTR);
 
VOID main(VOID)
{
    HINSTANCE hinstLib;
    MYPROC ProcAdd,ProcAdd2;
    BOOL fFreeResult,fFreeResult2, fRunTimeLinkSuccess=FALSE,fRunTimeLinkSuccess2 = FALSE;

    // Get a handle to the DLL module.
 
    hinstLib = LoadLibrary(TEXT("Myputs"));

    // If the handle is valid, try to get the function address.
 
    if (hinstLib != NULL)
    {
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("myPuts"));
       LPVOID lpMsgBuf;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                      NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),// Default language
                       (LPTSTR) &lpMsgBuf,0,NULL);

       printf( (char*) lpMsgBuf);
       system("Pause");

        ProcAdd2 = (MYPROC) GetProcAddress(hinstLib, TEXT("changeValue"));

        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                      NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),// Default language
                       (LPTSTR) &lpMsgBuf,0,NULL);

       printf( (char*) lpMsgBuf);
       system("Pause");

        // If the function address is valid, call the function.

        if (NULL != ProcAdd)
        {
            fRunTimeLinkSuccess = TRUE;
            (ProcAdd) (TEXT("Message via DLL function\n"));
        }

        if (NULL != ProcAdd2)
        {
            fRunTimeLinkSuccess2 = TRUE;
            (ProcAdd2) (TEXT ("4,true" ) );
        }

        // Free the DLL module.

         fFreeResult2= fFreeResult = FreeLibrary(hinstLib);
    }

    // If unable to call the DLL function, use an alternative.

    if (! fRunTimeLinkSuccess)
    {


        printf("Message via alternative method\n");
    }

   if (! fRunTimeLinkSuccess2)
        printf("No se pudo invocar a la funcion: changeValue \n");


   system("Pause");
}



Las dos lineas en rojo de la aplicación es donde falla porque devuelve NULL, después uso la función GetLastError para buscar el error y es que no la encuentra.


Sobre lo del enlazado estático podrías específicarme en detalles qué es lo que hay que hacer desde C++ Builder. Leí lo que dice la ayuda y lo hice y no me funciona, me da error de linkeo porque no encuentra la entrada de la función en la DLL, algo parecido a lo anterior.
Lo que hice fue:

1) Añadir al proyecto el .Lib de la DLL
2) Ir a las opciones avanzadas de likeo y especificar en el "Delay Load" la el fichero .dll.

Saludos a todos, llevo un mes en esto y no he podido usar funciones de una DLL.  No sé que pasa, hago lo mismo que dice la ayuda y nada.
 :hola:

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: ¿cómo Cargar Una Dll?
« Respuesta #4 en: Martes 21 de Noviembre de 2006, 22:43 »
0
No uso Borland asi que te recomiendo usar el Google.

Para ver si las funciones estan exportadas correctamente podes usar el Dependency Walker:

http://www.dependencywalker.com/

Tienen que ser 100% exactas, coincidiendo todos los caracteres en case sensitive para que encuentre las funciones.

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.