[C con Clase] carga retrasada de una dll
Programante
programante en gmail.com
Lun Abr 9 21:43:14 CEST 2007
AntonioFrancisco Gimenez escribió:
> a ver eso ya lo he probao y todo lo que sea sin referenciar en el
> linker el .lib no funciona entonces el tema es sin referenciarlo
> siguiendo un metodo parecido a ese pero al hacer GetProcAddress me
> retornaba siempre nulo eso usando simplemente punteros a una funcion
> declarada de la forma:
>
> float __declspec(dllexport) suma(float a,float b) ;
>
> a continuación incluyo el código de la carga dinamica de la dll:
>
> hlibrary=LoadLibrary("dll.dll") ;
> if (!hlibrary)MessageBox(hwnd,"error cargar","error
> cargar",MB_OK);
> ptrfnsuma=(PFNSUMA) GetProcAddress(hlibrary,"suma") ;
> if (ptrfnsuma==NULL)
> MessageBox(hwnd,"error","error",MB_OK);
> ptrfnsuma(2,3);
> FreeLibrary(hlibrary);
>
> el tipo PFNSUMA lo declaro como:
>
> typedef float __stdcall (WINAPI* PFNSUMA)(float,float) ;
En principio el código parece correcto. Tras los MessageBox deberías
salir de la función y te olvidas de que tu función retorne el valor de
ptrfnsuma (que supongo estará declarado como PFNSUMA).
> al ejecutar el código de la carga dinamica todo va bien hasta que
> llamo a GetProcAddress que compruebo si me devuelve el puntero nulo y
> asi es
Preveo que la función que exportas no se llama suma. No es sólo
diferenciar suma de Suma y SUMA, sino que probablemente sea suma en 8 Esto
es así para diferenciar el tipo de convención de llamada y que no se
pueda enlazar sin querer con otra. En stdcall es nombre@<tamaño
parámetros>, en la convención C se les antepone un prefijo, etc.
Si la librería está compilada como C++ la cosa puede ser aún peor,
puesto que el nombre se decora (name mangling) para que contenga
información sobre los parámetros, y para colmo el decorado es diferente
para cada compilador. Así que podrías tener wqapsuma en 8
Normalmente nos interesará que se exporte como suma, pero por defecto
los compiladores adornarán el nombre exportado. ¿Cómo saber el nombre
*real* de la función?
Mencionas que tienes Visual C++, entre las utilidades hay una que es
dumpbin que nos permite saber precisamente eso:
dumpbin /exports retrasada.dll
nos dará todas las funciones que exporta. Y ahora sí, con el nombre de
verdad.
Si el problema es ese, tienes dos formas de solucionarlo:
-El fácil: Cambiar tu código de GetProcAddress, para que llame a
"wqapsuma en 8"
-El más complicado: Compilar la biblioteca para que la función se
exporte como 'suma'. Normalmente tendremos que realizar un archivo .dep
donde indicaremos el nombre real, el deseado, y el ordinal a indicarle.
Aunque algunos compiladores tienen opciones más rápidas, como
--add-stdcall-alias en los GNU (pasárselo de parámetro al linker), que
produce las funciones también sin el @...
> ya ab urrido de dar vueltas buscando el porque sin saber porque me
> fallaba lei que existia una forma de carga de dlls llamada carga
> retrasada o delay load que se le expecifica al linker y el programa
> carga la dll solo si se accede a un recurso que asi lo requiera que es
> justo lo que quiero hacer venia un ejemplo para ms visual c++ decia
> que se supone que todos los linker tienen opciones parecidas, he
> encontrado tb indicaciones de esto en el msdn on line y por eso he
> hecho tal pregunta en este foro, que es donde me nutro de información
> acerca del compilador mingw(devcpp), aunque si me explicas porque no
> me funciona lo del GetProcAddress perfecto pues tambien me sirve.
>
> Saludos
Miraré sobre el delay load.
Saludos
Más información sobre la lista de distribución Cconclase