Comment puis-je appeler une fonction présente dans une DLL win32 ?
Virtual Library Interfaces ou comment ajouter l'appel dynamique à P/Invoke
Présenté par Olivier Dahan lors des Borland Devtracks (Mars 2005).
Voir l'aide en ligne :
ms-help://borland.bds3/bds3dnetguide/html/VirtualLibraryInterfaces.htm
- Simplifie l’importation de DLL Win32 sous .Net
- Ajoute la flexibilité indispensable pour le « Late Binding » absent de P/Invoke
Probléme avec P/Invoke : peu pratique, verbeux, le nom de la DLL ou son chemin ne peut être résolu au runtime si la DLL n’est pas trouvée cela provoque une erreur d’exécution.
Déclaration originale dans la DLL Win32 :
1 2 3
|
Function ConvertCtoF(CentValue: Integer): Integer; stdcall;
Function ConvertFtoC(FahrValue: Integer): Integer; stdcall; |
Déclaration typique P/Invoke sous .Net utilisant les attributs personnalisés :
1 2 3 4 5
|
[DllImport('Win32DLL.dll', CharSet = CharSet.Auto, EntryPoint = 'ConvertCtoF')]
Function ConvertCtoF; external;
[DllImport('Win32DLL.dll', CharSet = CharSet.Auto, EntryPoint = 'ConvertFtoC')]
Function ConvertFtoC; external; |
Un exemple VLI
Il est nécessaire d'effectuer les trois opérations suivantes :
1 - Ajouter Borland.Vcl.Win32 à la clause uses.
1 2
|
Uses Borland.Vcl.Win32; |
2 - Déclarer une interface contenant les fonctions exportées et non managées que vous souhaitez appeler.
1 2 3 4 5 6 7
|
type
// Il n'est pas nécessaire d'utiliser l'attribut DllImport sur ce prototype.
IWin32DLLInt = interface
function ConvertCtoF(CentValue: Integer): Integer;
function ConvertFtoC(FahrValue: Integer): Integer;
end; |
3 - Appeler la fonction
Supports pour vérifier que la DLL non managée existe et que les fonctions dans la déclaration d'interface sont vraiment exportées.
1 2 3 4 5 6 7 8 9 10
|
var MyDLL : String; // Nom complet de la DLL
MyWin32DLL : IWin32DLLInt; // Interface contenant les fonctions exportées et non managées
begin
MyDLL := ExtractFilePath(Application.ExeName) +'\mylib\Win32DLL.dll';
// Appel à travers linterface
if not SysUtils.Supports(MyDLL, IWin32DLLInt, MyWin32DLL)
then Writeln('Ne peut charger Win32DLL.dll') // Erreur
else NewInt := MyWin32DLL.ConvertCtoF(100); // Appel de la fonction de la DLL non-managée |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
program FaqDLL;
{$APPTYPE CONSOLE}
uses
Borland.Vcl.Win32,
SysUtils;
type
// Il n'est pas nécessaire d'utiliser l'attribut DllImport sur ce prototype.
IWin32DLLInt = interface
function ConvertCtoF(CentValue: Integer): Integer;
function ConvertFtoC(FahrValue: Integer): Integer;
end;
var MyDLL : String; // Nom complet de la DLL
MyWin32DLL : IWin32DLLInt; // Interface contenant les fonctions exportées et non managées
NewInt : Integer;
begin
MyDLL := ExtractFilePath(Environment.GetCommandLineArgs[0]) +'\mylib\Win32DLL.dll';
// Si la fonction Supports renvoie True, la DLL prend en charge toutes les fonctions nommées dans
// la déclaration de l'interface, et vous savez donc que leur appel est sans danger.
if not SysUtils.Supports(MyDLL, IWin32DLLInt, MyWin32DLL)
then Writeln('Ne peut charger Win32DLL.dll') // Erreur
else NewInt := MyWin32DLL.ConvertCtoF(100); // Appel de la fonction de la DLL non-managée
Readln;
end. |
Partager