locked
Communication WinForm-Dll RRS feed

  • Question

  • Bonjour,

    Je développe une application WinForm en VB.NET et une DLL en C# qui comporte également une WinForm.
    L'application lance la WinForm de la DLL (par un New de la classe suivi d'un Show). Cette DLL doit ensuite transmettre des données à l'application (par exemple des paramètres).

    Ma question : comment réaliser cette communication de la DLL vers l'application ? Quel mécanisme utiliser ? Par exemple, l'application peut-elle fournir l'adresse d'une procédure à sa DLL ?

    En d'autres termes : comment une application VB.NET peut-elle exporter une interface vers une DLL ?

    Avez-vous un example ?

    Merci de vos bonnes idées.

    Alain
    • Modifié AchLog vendredi 7 août 2009 17:04
    vendredi 7 août 2009 08:10

Réponses

  • Bonjour,

    Normalement il faut faire attention à ce genre de concept :
    Si A communique (dépend de) avec B et B communique avec A, alors A et B devrait être dans le même assembly.

    Maintenant pour palier à ce problème, il faut :
    - mettre une interface "I" dans votre DLL contenant une méthode "AppelDepuisDLL".
    - mettre une classe implémentant cette interface dans votre application WinForm. (Le code de la méthode sera, le code appellé par la DLL).

    - Lorsque vous appellez votre fenêtre dans la DLL, vous devez avant crée une instance de la classe créeé précédemment.
    - Il faut ensuite passer cette instance à votre DLL.
    - La DLL ne connait pas la classe elle même, mais sait que l'objet que vous lui envoyé implémente l'interface "I". Votre DLL peut donc appeller la méthode "AppelDepuisDLL".

    Automatiquement la méthode présente dans la classe qui implémente "I" sera exécutée.

    Est-ce clair ?

    Cordialement

    Gilles TOURREAU - MVP C#
    • Marqué comme réponse Gilles TOURREAU mercredi 19 août 2009 20:29
    • Marqué comme réponse AchLog jeudi 20 août 2009 10:29
    dimanche 9 août 2009 12:40
  • Bonjour,

    C'est casiment le même concept, mais en moins propre, en moins orienté objet et très technique.

    Cordialement
    Gilles TOURREAU - MVP C#
    mercredi 19 août 2009 20:28

Toutes les réponses

  • Bonjour,

    Normalement il faut faire attention à ce genre de concept :
    Si A communique (dépend de) avec B et B communique avec A, alors A et B devrait être dans le même assembly.

    Maintenant pour palier à ce problème, il faut :
    - mettre une interface "I" dans votre DLL contenant une méthode "AppelDepuisDLL".
    - mettre une classe implémentant cette interface dans votre application WinForm. (Le code de la méthode sera, le code appellé par la DLL).

    - Lorsque vous appellez votre fenêtre dans la DLL, vous devez avant crée une instance de la classe créeé précédemment.
    - Il faut ensuite passer cette instance à votre DLL.
    - La DLL ne connait pas la classe elle même, mais sait que l'objet que vous lui envoyé implémente l'interface "I". Votre DLL peut donc appeller la méthode "AppelDepuisDLL".

    Automatiquement la méthode présente dans la classe qui implémente "I" sera exécutée.

    Est-ce clair ?

    Cordialement

    Gilles TOURREAU - MVP C#
    • Marqué comme réponse Gilles TOURREAU mercredi 19 août 2009 20:29
    • Marqué comme réponse AchLog jeudi 20 août 2009 10:29
    dimanche 9 août 2009 12:40
  • Bonjour Gilles et merci pour la réponse.

    La nuit portant conseil, j'ai trouvé une solution simple qui fonctionne : un "delegate" qui, dans la DLL contient l'adresse de la procédure du programme principal traitant les données fournies par cette DLL.

    DLL et programme principal sont dans deux assembly différents, l'un en C#, l'autre en VB.NET.

    La DLL en C# contient :

    public delegate void ProcInputImage (ImgInfo msg);    // Prototype
    public ProcInputImage ExUserProc = null;                    // Déclaration de la variable public ExUserProc

    où ImgInfo est une structure de données contenant les infos a échanger.

    public struct ImgInfo
    {
    ......
    }

    La DLL expose également une procédure qui permet au programme principal d'initialiser la variable ExUserProc :

    public void DefProc (ProcInputImage pim)
    {
           ExUserProc = pim;
    }

    Pour envoyer les infos vers le programme principal la DLL initialise un structure ImgInfo et exécute la procédure ExUserProc :

    ImgInfo msg = new ImgInfo ();
    ...
    ExUserProc(msg);




    Le programme principal, en VB, quant à lui crée une instance de la classe DLL (soit dll) puis lui fournit l'adresse de sa procédure de traitement des données :
    dll.DefProc (AddressOf InputMessage)

    avec :

    Public Sub InputMessage (ByVal msg As dll.ImgInfo)
    ....
    End Sub


    Cette façon de faire n'implémente pas réellement d'Interface mais revient peut-être un peu au même ?

    Cordialement.


    Alain
    samedi 15 août 2009 09:01
  • Bonjour,

    C'est casiment le même concept, mais en moins propre, en moins orienté objet et très technique.

    Cordialement
    Gilles TOURREAU - MVP C#
    mercredi 19 août 2009 20:28
  • Ok Merci Gilles,

    Maintenant que "ça marche" tel que je l'ai fait, je vais essayer d'implémenter votre méthode. Mais je n'ai jamais encore manipulé les Interfaces.
    Auriez-vous un petit exemple concernant votre proposition ci-dessus ? Mais je ne veux pas abuser...

    Cordialement
    Alain
    jeudi 20 août 2009 10:31
  • Bonjour,

    Pas de problème ! Soit 2 projets "ProjetExe" et "ProjetDLL". "ProjetExe" contient une référence à "ProjetDLL".

    Dans ProjetDLL, il faut créer une interface comme ceci :

    public interface IMonInterface
    {
        void AppelDepuisDLL();
    }
    Ensuite on ajoute une classe dans ProjetDLL représentant une fonctionnalité qui va être appellée par notre ProjetExe (avec une méthode appellée Traitement(). Cette méthode traitement, va prendre en paramètre un objet qui implémente l'interface précédente et va appeller la méthode AppelDepuisDLL() de cet objet :

    public class Fonctionnalité
    {
        public void Traitement(IMonInterface objetInterface)
        {
            Console.WriteLine("Mon traitement...");
    
            // Appeler la méthode AppelDepuisDLL de l'objet passé en paramètre
            objetInterface.AppelDepuisDLL();
        }
    }
    Maintenant du côté du ProjetExe, nous allons implémenter cette interface (l'interface est accessible, car ProjetExe référencie ProjetDLL et donc peux accéder à tous les objets et interfaces de ce projet).

    public class ImplémentationMonInterface : IMonInterface
    {
        public void AppelDepuisDLL()
        {
            Console.WriteLine("J'ai été appellé par la DLL !!!");
        }
    }
    C'est une instance de cet objet que l'on passera en paramètre lors de l'appel à la méthode Fonctionnalité.Traitement(). Maintenant dans le Main du ProjetExe, il suffit d'ajouter :

    class Program
    {
        static void Main(string[] args)
        {
            // Création d'une instance de ImplémentationMonInterface
            ImplémentationMonInterface implémentation;
            implémentation = new ImplémentationMonInterface();
    
            // Création d'une instance de la fonctionnalité
            Fonctionnalité fonctionnalité;
            fonctionnalité = new Fonctionnalité();
    
            // Appeller la méthode Traitement de Fonctionnalité
            fonctionnalité.Traitement(implémentation);
        }
    }
    N'hésitez pas à utiliser le débogueur de Visual Studio, pour bien comprendre pas à pas comment fonctionne cet exemple.

    Cordialement







    Gilles TOURREAU - MVP C# - Architecte .NET/Consultant/Formateur
    jeudi 20 août 2009 20:19