Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
dynamique et de vérifier la version avant de charger les points
d'entrée par un "GetProcAddress". Le problème c'est que c'est
franchement "lourd".
Merci pour vos idées.
Mon blog RSS : http://yarglah.free.fr/monblog_rss.php <<
Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
dynamique et de vérifier la version avant de charger les points
d'entrée par un "GetProcAddress". Le problème c'est que c'est
franchement "lourd".
Merci pour vos idées.
Mon blog RSS : http://yarglah.free.fr/monblog_rss.php <<
Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
dynamique et de vérifier la version avant de charger les points
d'entrée par un "GetProcAddress". Le problème c'est que c'est
franchement "lourd".
Merci pour vos idées.
Mon blog RSS : http://yarglah.free.fr/monblog_rss.php <<
Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
dynamique et de vérifier la version avant de charger les points
d'entrée par un "GetProcAddress". Le problème c'est que c'est
franchement "lourd".
Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
dynamique et de vérifier la version avant de charger les points
d'entrée par un "GetProcAddress". Le problème c'est que c'est
franchement "lourd".
Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
dynamique et de vérifier la version avant de charger les points
d'entrée par un "GetProcAddress". Le problème c'est que c'est
franchement "lourd".
Jean-Yves wrote:
> Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
> dynamique et de vérifier la version avant de charger les points
> d'entrée par un "GetProcAddress". Le problème c'est que c'est
> franchement "lourd".
Bonjour,
Une petite correction tout d'abord: une DLL est toujours chargée
dynamiquement (Dynamic Link Library). Elle peut être chargée
implicitement (édition de liens avec la bibliothèque d'import) ou
explicitement (LoadLibrary).
Une solution consiste à faire du Delay Loading (à préciser au moment du
link). La DLL ne sera chargée qu'au moment de l'utilisation, ce qui vous
laisse éventuellement le temps (c'est selon) de vérifier la version
avant l'utilisation de la première fonction dans la DLL. Le Delay
Loading
Une autre solution est de faire du chargement implicite quand même mais
sans se fatiguer à faire des GetProcAddress. Mais comment est-ce
possible me direz vous? En utilisant la capacité des DLLs Win32 à
exporter des données. Prenons un petit exemple issu d'un des TPs que
j'utilise pendant mes cours.
Supposons une DLL qui exporte les fonctions suivantes:
int APIENTRY _StartSelection (HWND, POINT, LPRECT, int);
int APIENTRY _UpdateSelection (HWND, POINT, LPRECT, int);
int APIENTRY _EndSelection (POINT, LPRECT);
int APIENTRY _ClearSelection (HWND, LPRECT, int);
Je déclare dans mon fichier .H la structure suivante:
typedef int (* APIENTRY STARTSELECTION) (HWND, POINT, LPRECT, int);
typedef int (* APIENTRY UPDATESELECTION) (HWND, POINT, LPRECT, int);
typedef int (* APIENTRY ENDSELECTION) (MPOINT, LPRECT);
typedef int (* APIENTRY CLEARSELECTION) (HWND, LPRECT, int);
typedef struct tagFunctionTable {
STARTSELECTION StartSelection;
UPDATESELECTION UpdateSelection;
ENDSELECTION EndSelection;
CLEARSELECTION ClearSelection;
} FUNCTION_TABLE;
et une variable globale dans ma DLL de type FUNCTION_TABLE :
FUNCTION_TABLE Function_Table;
Dans le DllMain, je renseigne la table avec les adresses effectives
(cela sera fait à chaque chargement de la DLL puisque l'adresse de la
fonction peut varier d'un process client à l'autre):
BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID
lpReserved)
{
UNREFERENCED_PARAMETER(hInst);
UNREFERENCED_PARAMETER(lpReserved);
if (ul_reason_being_called == DLL_PROCESS_ATTACH)
{
Function_Table.StartSelection = (STARTSELECTION)
_StartSelection;
Function_Table.UpdateSelection = (UPDATESELECTION)
_UpdateSelection;
Function_Table.EndSelection = (ENDSELECTION) _EndSelection;
Function_Table.ClearSelection = (CLEARSELECTION)
_ClearSelection;
}
return 1;
}
Dans mon .DEF, je ne fais un export que de Function_table, pas des
fonctions:
EXPORTS Function_Table CONSTANT
-----------------------------
Dans le programme client, j'inclus le fichier .H de la DLL et je déclare
ma table de fonctions:
FUNCTION_TABLE *Functions;
Ensuite, pendant l'initialisation du programme (ou plus tard - après
avoir vérifié la présence et la version de la DLL), je charge ma table:
hDLL = LoadLibrary("MADLL.DLL");
if (hDLL != NULL)
{
// Recherche un point d'entrée unique pour les fonctions appelées
// Cette méthode n'est pas obligatoire et ne sera pas mise en oeuvre
// dans le cas de la mixité 16-32 bits
Functions = (FUNCTION_TABLE*) GetProcAddress (hDLL,
"Function_Table");
if (Functions == NULL)
{
FreeLibrary(hDLL);
return (0);
}
}
else
return (0);
Et voilà, en une seule passe, j'ai chargé toutes mes adresses. Il ne me
reste plus pour appeler les fonctions qu'à référencer ma table. Par
exemple:
Functions->UpdateSelection(hWnd, Point, &Rect, Shape);
Avantages de cette technique très simple à mettre en oeuvre:
- Un seul GetProcAddress
- Les noms des fonctions ne sont pas exportés (sécurité)
- Les noms des fonctions dans la table peuvent être différents des noms
réels des fonctions
--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Jean-Yves wrote:
> Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
> dynamique et de vérifier la version avant de charger les points
> d'entrée par un "GetProcAddress". Le problème c'est que c'est
> franchement "lourd".
Bonjour,
Une petite correction tout d'abord: une DLL est toujours chargée
dynamiquement (Dynamic Link Library). Elle peut être chargée
implicitement (édition de liens avec la bibliothèque d'import) ou
explicitement (LoadLibrary).
Une solution consiste à faire du Delay Loading (à préciser au moment du
link). La DLL ne sera chargée qu'au moment de l'utilisation, ce qui vous
laisse éventuellement le temps (c'est selon) de vérifier la version
avant l'utilisation de la première fonction dans la DLL. Le Delay
Loading
Une autre solution est de faire du chargement implicite quand même mais
sans se fatiguer à faire des GetProcAddress. Mais comment est-ce
possible me direz vous? En utilisant la capacité des DLLs Win32 à
exporter des données. Prenons un petit exemple issu d'un des TPs que
j'utilise pendant mes cours.
Supposons une DLL qui exporte les fonctions suivantes:
int APIENTRY _StartSelection (HWND, POINT, LPRECT, int);
int APIENTRY _UpdateSelection (HWND, POINT, LPRECT, int);
int APIENTRY _EndSelection (POINT, LPRECT);
int APIENTRY _ClearSelection (HWND, LPRECT, int);
Je déclare dans mon fichier .H la structure suivante:
typedef int (* APIENTRY STARTSELECTION) (HWND, POINT, LPRECT, int);
typedef int (* APIENTRY UPDATESELECTION) (HWND, POINT, LPRECT, int);
typedef int (* APIENTRY ENDSELECTION) (MPOINT, LPRECT);
typedef int (* APIENTRY CLEARSELECTION) (HWND, LPRECT, int);
typedef struct tagFunctionTable {
STARTSELECTION StartSelection;
UPDATESELECTION UpdateSelection;
ENDSELECTION EndSelection;
CLEARSELECTION ClearSelection;
} FUNCTION_TABLE;
et une variable globale dans ma DLL de type FUNCTION_TABLE :
FUNCTION_TABLE Function_Table;
Dans le DllMain, je renseigne la table avec les adresses effectives
(cela sera fait à chaque chargement de la DLL puisque l'adresse de la
fonction peut varier d'un process client à l'autre):
BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID
lpReserved)
{
UNREFERENCED_PARAMETER(hInst);
UNREFERENCED_PARAMETER(lpReserved);
if (ul_reason_being_called == DLL_PROCESS_ATTACH)
{
Function_Table.StartSelection = (STARTSELECTION)
_StartSelection;
Function_Table.UpdateSelection = (UPDATESELECTION)
_UpdateSelection;
Function_Table.EndSelection = (ENDSELECTION) _EndSelection;
Function_Table.ClearSelection = (CLEARSELECTION)
_ClearSelection;
}
return 1;
}
Dans mon .DEF, je ne fais un export que de Function_table, pas des
fonctions:
EXPORTS Function_Table CONSTANT
-----------------------------
Dans le programme client, j'inclus le fichier .H de la DLL et je déclare
ma table de fonctions:
FUNCTION_TABLE *Functions;
Ensuite, pendant l'initialisation du programme (ou plus tard - après
avoir vérifié la présence et la version de la DLL), je charge ma table:
hDLL = LoadLibrary("MADLL.DLL");
if (hDLL != NULL)
{
// Recherche un point d'entrée unique pour les fonctions appelées
// Cette méthode n'est pas obligatoire et ne sera pas mise en oeuvre
// dans le cas de la mixité 16-32 bits
Functions = (FUNCTION_TABLE*) GetProcAddress (hDLL,
"Function_Table");
if (Functions == NULL)
{
FreeLibrary(hDLL);
return (0);
}
}
else
return (0);
Et voilà, en une seule passe, j'ai chargé toutes mes adresses. Il ne me
reste plus pour appeler les fonctions qu'à référencer ma table. Par
exemple:
Functions->UpdateSelection(hWnd, Point, &Rect, Shape);
Avantages de cette technique très simple à mettre en oeuvre:
- Un seul GetProcAddress
- Les noms des fonctions ne sont pas exportés (sécurité)
- Les noms des fonctions dans la table peuvent être différents des noms
réels des fonctions
--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Jean-Yves wrote:
> Bien sur vous allez me dire que je n'ai qu'à utiliser la DLL en link
> dynamique et de vérifier la version avant de charger les points
> d'entrée par un "GetProcAddress". Le problème c'est que c'est
> franchement "lourd".
Bonjour,
Une petite correction tout d'abord: une DLL est toujours chargée
dynamiquement (Dynamic Link Library). Elle peut être chargée
implicitement (édition de liens avec la bibliothèque d'import) ou
explicitement (LoadLibrary).
Une solution consiste à faire du Delay Loading (à préciser au moment du
link). La DLL ne sera chargée qu'au moment de l'utilisation, ce qui vous
laisse éventuellement le temps (c'est selon) de vérifier la version
avant l'utilisation de la première fonction dans la DLL. Le Delay
Loading
Une autre solution est de faire du chargement implicite quand même mais
sans se fatiguer à faire des GetProcAddress. Mais comment est-ce
possible me direz vous? En utilisant la capacité des DLLs Win32 à
exporter des données. Prenons un petit exemple issu d'un des TPs que
j'utilise pendant mes cours.
Supposons une DLL qui exporte les fonctions suivantes:
int APIENTRY _StartSelection (HWND, POINT, LPRECT, int);
int APIENTRY _UpdateSelection (HWND, POINT, LPRECT, int);
int APIENTRY _EndSelection (POINT, LPRECT);
int APIENTRY _ClearSelection (HWND, LPRECT, int);
Je déclare dans mon fichier .H la structure suivante:
typedef int (* APIENTRY STARTSELECTION) (HWND, POINT, LPRECT, int);
typedef int (* APIENTRY UPDATESELECTION) (HWND, POINT, LPRECT, int);
typedef int (* APIENTRY ENDSELECTION) (MPOINT, LPRECT);
typedef int (* APIENTRY CLEARSELECTION) (HWND, LPRECT, int);
typedef struct tagFunctionTable {
STARTSELECTION StartSelection;
UPDATESELECTION UpdateSelection;
ENDSELECTION EndSelection;
CLEARSELECTION ClearSelection;
} FUNCTION_TABLE;
et une variable globale dans ma DLL de type FUNCTION_TABLE :
FUNCTION_TABLE Function_Table;
Dans le DllMain, je renseigne la table avec les adresses effectives
(cela sera fait à chaque chargement de la DLL puisque l'adresse de la
fonction peut varier d'un process client à l'autre):
BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID
lpReserved)
{
UNREFERENCED_PARAMETER(hInst);
UNREFERENCED_PARAMETER(lpReserved);
if (ul_reason_being_called == DLL_PROCESS_ATTACH)
{
Function_Table.StartSelection = (STARTSELECTION)
_StartSelection;
Function_Table.UpdateSelection = (UPDATESELECTION)
_UpdateSelection;
Function_Table.EndSelection = (ENDSELECTION) _EndSelection;
Function_Table.ClearSelection = (CLEARSELECTION)
_ClearSelection;
}
return 1;
}
Dans mon .DEF, je ne fais un export que de Function_table, pas des
fonctions:
EXPORTS Function_Table CONSTANT
-----------------------------
Dans le programme client, j'inclus le fichier .H de la DLL et je déclare
ma table de fonctions:
FUNCTION_TABLE *Functions;
Ensuite, pendant l'initialisation du programme (ou plus tard - après
avoir vérifié la présence et la version de la DLL), je charge ma table:
hDLL = LoadLibrary("MADLL.DLL");
if (hDLL != NULL)
{
// Recherche un point d'entrée unique pour les fonctions appelées
// Cette méthode n'est pas obligatoire et ne sera pas mise en oeuvre
// dans le cas de la mixité 16-32 bits
Functions = (FUNCTION_TABLE*) GetProcAddress (hDLL,
"Function_Table");
if (Functions == NULL)
{
FreeLibrary(hDLL);
return (0);
}
}
else
return (0);
Et voilà, en une seule passe, j'ai chargé toutes mes adresses. Il ne me
reste plus pour appeler les fonctions qu'à référencer ma table. Par
exemple:
Functions->UpdateSelection(hWnd, Point, &Rect, Shape);
Avantages de cette technique très simple à mettre en oeuvre:
- Un seul GetProcAddress
- Les noms des fonctions ne sont pas exportés (sécurité)
- Les noms des fonctions dans la table peuvent être différents des noms
réels des fonctions
--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr