OVH Cloud OVH Cloud

LoadLibrary et GetProcAddress

40 réponses
Avatar
PurL
Bonjour,

Comment, dans un programme, peut-on utiliser les fonctions LoadLibrary et
GetProcAddress (faisant parties de l'API windows), sans inclure le .h
correspondant ?

PurL

10 réponses

1 2 3 4
Avatar
Fabien SK
AMcD wrote:

Fabien SK wrote:


Arggggg ! Quand je dis "statiquement", c'est que ton module a besoin
de XXX.dll pour se charger. Quand tu fais un "Dependancy Walker"
(http://www.dependencywalker.com/), tu vois bien que ton programme a
besoin de telle ou telle DLL pour être chargé par le système. Bien
sûr, on n'inclut pas le code des DLLs tierces dans son programme
(sinon çà ne s'appellerait pas des DLLs).




Hem, t'es sûr là ? Statique c'est l'inverse de ce que tu dis. Toi, ce que tu
nous décrit c'est du dynamique...



Comment nommes-tu le fait d'utiliser une DLL:
- en spécifiant au link la liaison entre ton programme et la DLL ?
(chargement de la DLL lors de la création du process par le système)
- en chargeant la DLL avec "LoadLibrary" ? (chargement de la DLL pendant
l'exécution du programme)

Moi je n'ai pas d'autres mots pour dire ça. D'un coté la dépendance est
statique, et de l'autre non. Si tu as une autre manière de dire ça, je
suis preneur.
Avatar
Fabien SK
> C'est vous qui l'avez donné le prototype ! et je ne vois pas en quoi il
n'est pas conforme.
la convention d'appel c'est réglé, c'est du "stdcall" et y'a pas
d'inderterminé la dessus.




C'est bon, j'ai un exemple qui marche avec Visual C++ 6 (compilé en C).

__declspec(dllimport) struct HINSTANCE__* __stdcall LoadLibraryA(const
char*);

int main(int argc, char *argv[])
{

void *ptr = LoadLibraryA("kernel32.dll");

return 0;
}
Avatar
Vincent Burel
"Fabien SK" <fabsk+ wrote in message
news:3f8cf4cb$0$13291$
AMcD wrote:

> Fabien SK wrote:
>
>
>>Arggggg ! Quand je dis "statiquement", c'est que ton module a besoin
>>de XXX.dll pour se charger. Quand tu fais un "Dependancy Walker"
>>(http://www.dependencywalker.com/), tu vois bien que ton programme a
>>besoin de telle ou telle DLL pour être chargé par le système. Bien
>>sûr, on n'inclut pas le code des DLLs tierces dans son programme
>>(sinon çà ne s'appellerait pas des DLLs).
>
>
> Hem, t'es sûr là ? Statique c'est l'inverse de ce que tu dis. Toi, ce


que tu
> nous décrit c'est du dynamique...

Comment nommes-tu le fait d'utiliser une DLL:
- en spécifiant au link la liaison entre ton programme et la DLL ?
(chargement de la DLL lors de la création du process par le système)
- en chargeant la DLL avec "LoadLibrary" ? (chargement de la DLL pendant
l'exécution du programme)

Moi je n'ai pas d'autres mots pour dire ça. D'un coté la dépendance est
statique, et de l'autre non. Si tu as une autre manière de dire ça, je
suis preneur.



la dépendance est forcément statique, puisqu'on est bien obligé de stipuler
cette dépendance dans le programme qui en a besoin. Mais le Link est
dynamique dans le sens où le code n'est pas inclu dans le programme d'une
part, et le lien explicite est réalisé par le système d'exploitation au
lancement du programme (pas par le Linker), d'autre part.

A mon avis vous faites une confusion sur ce que l'on appelle un Link
Dynamique et un Link Statique.

Vincent Burel
Avatar
Vincent Burel
"Fabien SK" <fabsk+ wrote in message
news:3f8cf4cb$0$13291$
Comment nommes-tu le fait d'utiliser une DLL:
- en spécifiant au link la liaison entre ton programme et la DLL ?
(chargement de la DLL lors de la création du process par le système)



Link dynamique.

- en chargeant la DLL avec "LoadLibrary" ? (chargement de la DLL pendant
l'exécution du programme)



ce n'est pas un link. tout simplement, car le linker ne fait rien ici, c'est
le programme qui fait tout le boulot. Il pourrai tout aussi bien charger un
DLL pour uniquement lister les ressources, ou récupérer l'icone premier, ce
n'est toujours pas pas un link...

Vincent Burel
Avatar
Vincent Burel
"Fabien SK" <fabsk+ wrote in message
news:3f8cf691$0$13299$
> C'est vous qui l'avez donné le prototype ! et je ne vois pas en quoi il
> n'est pas conforme.
> la convention d'appel c'est réglé, c'est du "stdcall" et y'a pas
> d'inderterminé la dessus.
>

C'est bon, j'ai un exemple qui marche avec Visual C++ 6 (compilé en C).

__declspec(dllimport) struct HINSTANCE__* __stdcall LoadLibraryA(const
char*);

int main(int argc, char *argv[])
{

void *ptr = LoadLibraryA("kernel32.dll");

return 0;
}



Ha ben oui sur LoadLibrary y'a plusieurs fonction, il faut prendre la bonne.
Mais je croyais qu'on parlais de GetProcAddress (là y'a qu'un fonction).

VB
Avatar
Fabien SK
>>Comment nommes-tu le fait d'utiliser une DLL:
- en spécifiant au link la liaison entre ton programme et la DLL ?
(chargement de la DLL lors de la création du process par le système)
- en chargeant la DLL avec "LoadLibrary" ? (chargement de la DLL pendant
l'exécution du programme)

Moi je n'ai pas d'autres mots pour dire ça. D'un coté la dépendance est
statique, et de l'autre non. Si tu as une autre manière de dire ça, je
suis preneur.



la dépendance est forcément statique, puisqu'on est bien obligé de stipuler
cette dépendance dans le programme qui en a besoin. Mais le Link est
dynamique dans le sens où le code n'est pas inclu dans le programme d'une
part, et le lien explicite est réalisé par le système d'exploitation au
lancement du programme (pas par le Linker), d'autre part.



Préambule: son problème était d'accéder aux fonctions "LoadLibrary" et
"GetProcAddress" (ça aurait pu être "CreateWindow", le problème aurait
été le même).

Ca tombe bien, ma première réponse à PurL était:

--- citation ---
Moi: Le .h n'est pas important. Tu peux réécrire le prototype dans ton
code. C'est le .lib qu'il te faut, ce qu'il va faire que ton .exe ou ta
.dll va dépendre statiquement de kernel32.dll
---

Note que je n'ai pas écrit "linker statiquement kernel32.dll".
Ce à quoi tu me réponds:

--- citation ---
Toi: s'il utilise LoadLibrary et GetProcAddress , il n'a pas besoin du .LIB
[je passe la partie où tu m'expliques ce qu'est une DLL, un .LIB et un link]
---

Vu qu'il veut accéder à la fonction "LoadLibrary", il a besoin de
kernel.lib (tu n'avais pas compris son problème). Donc j'essaye de
reexpliquer tout ça:

--- citation ---
Moi: "kernel32.lib" _fait_ que le programme va dépendre statiquement de
"kernel32.dll".
Je ne connais pas d'autre moyen d'utiliser "LoadLibrary" que de linker
statiquement avec "kernel32.dll".
---

OK, j'ai dit "linker statiquement". Mais tout de même, je t'ai parlé
deux fois de dépendance statique au dessus.
Avatar
Fabien SK
AMcD wrote:

Fabien SK wrote:


Arggggg ! Quand je dis "statiquement", c'est que ton module a besoin
de XXX.dll pour se charger. Quand tu fais un "Dependancy Walker"
(http://www.dependencywalker.com/), tu vois bien que ton programme a
besoin de telle ou telle DLL pour être chargé par le système. Bien
sûr, on n'inclut pas le code des DLLs tierces dans son programme
(sinon çà ne s'appellerait pas des DLLs).



Hem, t'es sûr là ? Statique c'est l'inverse de ce que tu dis. Toi, ce que tu
nous décrit c'est du dynamique...



D'ailleurs (tiens, on commence à couper les cheveux en quatre), si je dis:
- "dépendance statique" et "dépendance dynamique", ça correspond bien à
ce que je veux dire
- "link statique" et "link dynamique", c'est pas bon.
Avatar
Fabien SK
Vincent Burel wrote:
"Fabien SK" <fabsk+ wrote in message
news:3f8cf691$0$13299$

C'est vous qui l'avez donné le prototype ! et je ne vois pas en quoi il
n'est pas conforme.
la convention d'appel c'est réglé, c'est du "stdcall" et y'a pas
d'inderterminé la dessus.




C'est bon, j'ai un exemple qui marche avec Visual C++ 6 (compilé en C).

__declspec(dllimport) struct HINSTANCE__* __stdcall LoadLibraryA(const
char*);

int main(int argc, char *argv[])
{

void *ptr = LoadLibraryA("kernel32.dll");

return 0;
}




Ha ben oui sur LoadLibrary y'a plusieurs fonction, il faut prendre la bonne.
Mais je croyais qu'on parlais de GetProcAddress (là y'a qu'un fonction).



__declspec(dllimport) void* __stdcall LoadLibraryA(const char*);
__declspec(dllimport) void* __stdcall GetProcAddress(void*, const char*);

int main(int argc, char *argv[])
{

void *ptr = LoadLibraryA("kernel32.dll");
void *ptr2 = GetProcAddress(ptr, "CreateMutexA");

return 0;
}

En fait, peut-être que son problème est qu'il utilise des prototypes C++
et pas des prototypes C. Le bout de code ci-dessus marche avec Visual
C++ 6 dans un fichier ".c". Par contre si je veux faire du C++, je dois
faire:

extern "C" __declspec(dllimport) void* __stdcall LoadLibraryA(const char*);

C'est peut-être pour ça qu'il ne trouve pas le symbole non plus pour
"GetProcAddress".
Avatar
adebaene
"PurL" wrote in message news:<bmh4u9$rc5$...

C'est une application qui sera distribuée avec le compilateur CPP de Borland
car elle sera capable de créér des dll puis de les utilisées juste après
(une sorte de plug'in) les fonctions disponibles dans ces dll seront
appelées par le couple LoadLibrary/GetProcAddress indirectement par le
programme puisqu'il ne peut connaitre avant le nom des dll et des fonctions
de ce fait je créée un DLL charnière "sur mesure" appelant les dll deja
existantes puis executant les nouvelles fonctions de l'utilisateurs.



Y'a un truc qui m'échappe là : LoadLibrary et GetProcAddress sont
appelées soit par ton programme, soit par ta DLL "charnière" (je ne
comprends pas trop à quoi elle sert mais bon....). Dans tous les cas,
il s'agit de code que tu écrits et compile sur ton poste de
développement, pas du code de tes DLLs plugins qui sont compilées sur
la machine cliente. Dans ces conditions, qu'est ce qui t'empêche
d'#inclure <windows.h> ?

A moins que tes DLLs plugins aient besoin d'appeler LoadLibray, il n'y
a pas de problèmes, ou alors j'ai rien comris à ce que tu veux
faire....

Arnaud
Avatar
PurL
> A moins que tes DLLs plugins aient besoin d'appeler LoadLibray, il n'y
a pas de problèmes, ou alors j'ai rien comris à ce que tu veux
faire....

Arnaud




Je vais essayer de réexpliquer :

Mon programme manipule des données d'acquisition.
L'utilisateur peut ecrire du code CPP pour "jouer" avec ces données (comme
les macro sous excel)
De plus, l'utilisateur peut avoir accès à des dll contenant des fonctions
(que j'appelle DLL bibliothèque) (j'en ai fait une par exemple pour les
fonctions mathèmatiques COS, SIN, ...)
Quand l'utilisateur à écrit son code, le programme compile ce code pour
créer une DLL (que j'ai appellé DLL charnière) capable d'appeler les DLL
bibliothèque (dans l'exemple celle qui contient les fonctions
mathématiques).
Donc les DLL bibliothèque sont effectivement créées sur mon poste donc là,
pas de probleme mais la DLL charniere c'est le programme principale qui la
créer sur le poste de l'utilisateur. Et cette DLL charnière à besoin de
LoadLibrary / GetProcAddress / FreeLibrary pour appeler les fonctions des
DLL bibliothèques.

Exemple d'un code source de la DLL charnière contenant le code de
l'utilisateur :
-----------debut DLL----------
unsigned int h0; //il y aura autant de h'i' que de DLL bibliothèque à
charger

//declaration de pointeurs de fonction permettant d'appeler les fonctions de
la DLL bibliothèque
typedef float (*typeCOS)(float a);
typeCOS COS;
typedef float (*typeSIN)(float a);
typeSIN SIN;
typedef float (*typeTAN)(float a);
typeTAN TAN;
typedef float (*typeLOG)(float a);
typeLOG LOG;
typedef float (*typeLN)(float a);
typeLN LN;
typedef float (*typePOW)(float a, float b);
typePOW POW;
typedef float (*typeEXP)(float a);
typeEXP EXP;


//procédure obligatoire de chargement de la DLL bibliothèque
//et d'initialisation des pointeurs de fonction
//c'est ici ou je veux pouvoir utilisé LoadLibrary et GetProcAddress
//sans embarquer tout le compilateur pour compiler la DLL charniere
extern "C" __declspec(dllexport) void __stdcall Init()
{
h0 = LoadLibrary("C:mathmath.dll");
COS = (typeCOS)GetProcAddress(h0, "COS");
SIN = (typeSIN)GetProcAddress(h0, "SIN");
TAN = (typeTAN)GetProcAddress(h0, "TAN");
LOG = (typeLOG)GetProcAddress(h0, "LOG");
LN = (typeLN)GetProcAddress(h0, "LN");
POW = (typePOW)GetProcAddress(h0, "POW");
EXP = (typeEXP)GetProcAddress(h0, "EXP");
}

//ensuite viennent les fonctions de l'utilisateur (2 fonctions dans
l'exemple)
//celles-ci ont toujours le meme prototype
//elles recoivent un pointeur sur le tableau de données à manipuler
//et retournent le résultat du calcul
//ces fonctions sont directement appelées par le programme principale aussi
//par LoadLibray / GetProcAddress et pour lui il n'y a pas de probleme
//puisque compilé sur mon poste
extern "C" __declspec(dllexport) float __stdcall Calcul0(float *GRD)
{
return COS(GRD[1] * 2); //on utilise une fonction de la DLL bibliotheque
}

extern "C" __declspec(dllexport) float __stdcall Calcul1(float *GRD)
{
return LOG(GRD[2]);
}

//procédure obligatoire
extern "C" __declspec(dllexport) void __stdcall Fin()
{
FreeLibrary(h0);
}
-----------fin DLL----------

en espérant avoir été un peu plus clair.

au passage, je vous remercie tous pour votre contribution active, ca fait
plaisir.

PurL
1 2 3 4