Comment créer des fonctions en C (dans des Dll standards) appelables depuis VB ?
Les Dll, pourquoi faire ?
Vous pouvez vouloir utiliser des Dll, souvent écrites dans d'autres langages que VB, pour diverses raisons telles qu'un besoin de performances ou pour une simple réutilisation de code existant. Par exemple, la fonction GetTickCount disponible dans la Dll Kernel32 peut être appelée et utilisée depuis un programme en VB avec une simple déclaration comme ceci :
Private Declare Function GetTickCount Lib "kernel32" () As Long
On peut aussi souhaiter écrire ses propres fonctions, dans ses propres Dll, et c'est ce que nous allons expliquer dans cet article;
On supposera le langage C connu, l'article se concentrant sur la génération d'une Dll appelable depuis VB.
Comment ça marche ?
Le but de cet article est de donner un exemple complet (et concret!) de réalisation d'une fonction en langage C dans une Dll, puis de sa déclaration et utilisation dans un programme en VB. Cet article expose la méthode pour faire ceci en C, mais il est possible de faire la même chose avec n'importe quel autre langage (C++, Fortran, etc.) pour autant que celui-ci dispose d'un compilateur permettant de générer une Dll standard.
Nous allons réaliser notre Dll avec Visual C++ 2005, Express Edition, essentiellement parce que celui-ci est téléchargeable gratuitement depuis le site de Microsoft, en suivant ce lien : Visual C++ 2005, Express Edition. Néanmoins, tout ce qui est expliqué ici est aisément transposable aux autres versions de Visual C++. Qui plus est, tout compilateur/environnement de développement capable de générer une Dll peut être utilisé.
Réalisation de la Dll
Dans cet article, nous allons implémenter une fonction très simple, permettant de déterminer si un nombre est pair ou non.
Le projet de cet exemple se nomme "samplevb" et la fonction "IsNumberEven".
Voici les étapes à suivre pour la création de la Dll :
- Créer un nouveau projet : Fichier->Nouveau Projet->EmptyProj (projet vide)
- Donner un nom au projet, puis cliquer sur ok
- Accéder au propriétés du Projet : Projet->Propriétés
- Dans la Combobox "Configuration", choisir "Toutes les configurations"
- Dans le volet de gauche, choisir Propriétés de configuration->Général
- Dans le volet de droite, changer la valeur de "Type de configuration" de "Application (exe) à "bibliothèque dynamique"
- Ajouter ensuite un fichier, qui va contenir votre fonction : Projet->Ajouter un nouvel élément
- Choisir Fichier c++ et saisissez un nom. Important :donner une extension .c à votre fichier - screenshot
- Accéder au propriétés du Projet : Projet->Propriétés
- Dans le volet de gauche, choisir Editeur de liens->Débogage, puis dans le panneau de droite, changer la valeur de "Génération d'un fichier de mappage" de "Non" à "Oui"
- Saisissez le code de votre (vos) fonction(s)
#define export __declspec (Dllexport)
export int __stdcall IsNumberEven( const long n) { return ((n & 1) ==0); }
Il y a 2 points très importants à noter :
- La fonction doit être précédée du mot export
- Entre le type (int) et le nom de la fonction (IsNumberEven), il faut ajouter la directive __stdcall
Le mot clé export indique à l'éditeur de lien que ces fonctions doivent être "exportées" (rendues disponibles), pour des appels depuis l'extérieur de la Dll.
La directive __stdcall permet de faire en sorte que les fonctions de la Dll et les fonctions de VB utilisent les mêmes conventions pour le passage des arguments. Un effet secondaire de la directive __stdcall est de changer légèrement le nom des fonctions générées. Dans notre exemple, la fonction "IsNumberEven" va être exportée sous le nom "_IsNumberEven@4". Ceci s'appelle une décoration. Nous allons voir dans la suite de l'article comment récupérer ce nom et comment en tenir compte dans la déclaration.
Il ne reste plus qu'à générer la Dll : Générer->Générer "nom de la Dll" (ici, samplevb). Si tout s'est bien passé, le panneau de sortie (en bas de l'IDE) doit afficher :
1>samplevb - 0 erreur(s), 0 avertissement(s) ========== Génération : 1 a réussi, 0 a échoué, 0 mis à jour, 0 a été ignoré ==========
Utilisation de la Dll
L'utilisation est très simple :
- Retrouver le nom d'export de la fonction : Editer le fichier de mappage (samplevb.map), il se trouve au même endroit que la Dll, et noter le nom interne de la fonction. Ici, le nom est "_IsNumberEven@4"
- Déclarer et utiliser la fonction dans le programme VB :
Option Explicit
Private Declare Function IsNumberEven Lib "samplevb.Dll" Alias "_IsNumberEven@4" (ByVal n As Long) As Long '
Private Sub Form_Load() Debug.Print IsNumberEven(122) End Sub
Redistribution et installation
Lors de la distribution ou de l'installation, il est bien sur nécessaire d'inclure la Dll et de spécifier un endroit pour elle-ci. Plusieurs endroits sont possibles, correspondants aux endroits ou Windows va chercher les Dll. Voici les endroits possibles : Dynamic-Link Libray Research Path.
Comme votre Dll n'est pas une Dll système, le meilleur endroit est probablement le répertoire de l'application.
Lors du développement, quand le programme est lancé depuis l'IDE, il faut un petit "truc" pour que le programme puisse trouver le chemin de la Dll :
#Const DebugVersion = 1
Private Declare Function SetEnvironmentVariable _ Lib "kernel32.dll" _ Alias "SetEnvironmentVariableA" _ ( _ ByVal lpName As String, _ ByVal lpValue As String _ ) _ As Long
Private Sub Form_Load() #If DebugVersion Then SetEnvironmentVariable "PATH", Environ$("PATH") & ";" & App.Path #End If
End Sub
Une solution alternative est de copier la Dll dans le répertoire système, par exemple : Windows\System32, juste le temps du développement de l'application.
Passage de paramètres et conversions de types entre C et VB
Le sujet est trop vaste pour être traité ici in-extenso, d'autant qu'il existe de nombreux articles très complets sur le sujet, notamment celui-ci : API Win32. Vous trouverez aussi à la fin de cet article de nombreux liens traitant de cela en détail.
Pour aller plus loin...
On trouve de très nombreux articles traitant de ce sujet, aussi bien chez Microsoft (MSDN LIbrary, KB) qu'ailleurs (Internet, Livres, etc.). Vous trouverez ici quelques liens très intéressants voire indispensables pour bien utiliser tout ceci :
|