IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

event dans une dll delphi a recuperer dans un autre langage


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2011
    Messages : 27
    Points : 19
    Points
    19
    Par défaut event dans une dll delphi a recuperer dans un autre langage
    Bonjour,

    Je suis relativement débutant en .net et complétement débutant en delphi.

    Mon projet utilise une IHM .NET, qui communique avec une dll en delphi7, et la dll 'commande' un robot.

    Hors j'ai besoin de récupérer les données (de position par exemple) du robot. Dans un premier temps j'ai essayé de faire cela par un système de callback:
    (mélangeant un peu, a priori, callback et event) mais pour ce que j'en ai compris une callback ne fonctionne qu'une fois, et chaque fois qu'elle a travaillé 1 fois, il faut la reinvoquer ....
    donc maintenant je pense qu'il faut que je créais un event dans la dll (premier problème), puis que j'arrive a récupérer l'event dans mon IHM (deuxieme probleme)

    Donc premier problème: l'event dans la dll
    Tous les exemples que j'ai trouvé sont fait pour fonctionner sur un component (donc une interface graphique) hors, dans mon cas la dll n'est qu'une bibliothèque de fonctions.

    deuxième problème: récupérer dans l'IHM l'event
    Ben là çà reste une question ouverte :p est-ce que ça se fait comme n'importe fonction? ou d'une manière particulière (comme l'event est censé envoyer des données seul et non en réponse?

    Merci de l'aide que vous pourrez m'apporter, n’hésitez pas à demander des explications si j'ai manqué de clarté, je ne suis pas un habitué des forum non plus .

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 256
    Points
    25 256
    Par défaut
    Tu évoques une DLL
    Tu as un exe .NET
    Tu as une DLL en Delphi

    Cette DLL est une collection de fonction exportée, ce n'est pas le plus pratique à utiliser en .NET, un objet automation (toujours en safecall) avec des interfaces (TLB) aurait été plus pratique surtout que cela propose nativement une gestion d'évènement

    Pense qu'un gestionnaire d'évènement, c'est un CallBack, après tout, tu passe un pointeur sur une fonction, avec un event, tu passes une méthode, il n'y a pas une grande différence !

    Je suppose que le Exe.NET lance une fonction de ta DLL qui dure un certains temps ou fonctionne de façon asynchrone, tu aimerais indiquer sa progression ou qu'elle se termine depuis la DLL vers l'EXE

    Pour cela un CallBack, semble tout à fait approprié, il faut juste déclarer un prototype de fonction dans la DLL qui sera un paramètre à la fonction de traitement
    Du côte .NET, tu devras écrire une fonction qui répond au prototype de CallBack (valeur de retour, paramètre, convention d'appel)
    Je te conseille d'ajouter un autre paramètre qui serait le CallBackContext, un void* dont lequel tu pourrais stocker une valeur de l'Exe.NET, la DLL ne faisait que passer cette valeur à la fonction CallBack, du côte Exe.Net, tu pourras utiliser de CallBackContext (pointeur sur un objet pour savoir comment réagir)

    Bon, le .NET étant un langage "managé", cela peut-être pénible à créer un CallBack (déjà que la convertion d'appel safecall, comme forcer un pointeur de fonction et non un pointeur de méthode ... )
    L'autre solution serait de définir une Interface dans la DLL, lors de l'appel de la fonction de traitement, le Exe.NET passe un objet implémentant l'interface comme paramètre !
    C'est très proche du fonctionnement des Event COM

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2011
    Messages : 27
    Points : 19
    Points
    19
    Par défaut
    Merci pour la réponse rapide, cependant il y a encore des chose qui ne sont pas claire.

    1) Concernant la DLL delphi que j'utilise: j'en ai hérité de mes prédécesseurs et n'ai pas le loisir de la refaire de zéro, un peu la modifier et rajouter quelques choses sont la limites de ce que je peux y faire actuellement

    2)Mon contexte:
    - depuis l'IHM je lance un cycle de déplacement du robot
    - pendant se déplacement je veux connaitre certaines données (ex: la position) au fur et a mesure qu'il bouge
    - comme il faut limiter les échanges je souhaite que pendant ce cycle la dll (qui contrôle le robot) renvoie a l'IHM toute seule les données (sans avoir a en faire la requête depuis l'IHM toute les 10 ms par exemple)

    3)Si j'ai bien compris ce que tu disais, tu me confirme qu'une 'callback' ne répond qu'une fois ?

    4) dernier point quand tu parles de passer une interfaces veux tu dires quelque chose comme un pointeur du cote .Net qui sera remplis par la fonction contenue dans la dll et renvoyé ainsi ? (je croyais que l'on ne pouvais échanger que des type simple (int, double, char ... pas de structure, pas de tableau, et pas de pointeur ?)

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 451
    Points
    28 451
    Par défaut
    pour autant que je sache, tu peux utiliser DLLImport pour récupérer sous .Net les fonctions exposées par la DLL Delphi (exports).

    reste plus qu'à passer à la DLL l'adresse d'une fonction callback que la DLL devra invoquer à chaque fois qu'elle a des données à remonter.

    maintenant, je ne sais pas comment fonctionne la DLL mais si elle permet simplement d'interroger l'état du robot, elle ne déclenchera rien d'elle-même...

  5. #5
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2011
    Messages : 27
    Points : 19
    Points
    19
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    maintenant, je ne sais pas comment fonctionne la DLL mais si elle permet simplement d'interroger l'état du robot, elle ne déclenchera rien d'elle-même...
    Pour l'instant en effet elle ne permet que d'interroger l’état du robot et de le commander, justement maintenant il faut rajouter la partie qui renvoie des informations d'elle même. C'est pour ça que j'évoquais mon besoin de création et de remontée d'event DANS la dll (le problème étant, si j'ai bien compris ce que disais ShaiLeTroll, de le faire seulement en ajoutant des fonctions et sans devoir tout casser :S)

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 451
    Points
    28 451
    Par défaut
    je ne vois pas bien ce que tu y gagnes de le faire dans la DLL..tu vas devoir créer un thread secondaire qui va périodiquement interroger le robot et déclencher la callback dans un contexte incertain.

    il serait sans doute plus simple de le faire depuis l'application hôte.

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 758
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 758
    Points : 13 357
    Points
    13 357
    Par défaut
    Ton robot ne suit-il pas les spécifications OPC ?

  8. #8
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Citation Envoyé par titou640 Voir le message
    3)Si j'ai bien compris ce que tu disais, tu me confirme qu'une 'callback' ne répond qu'une fois ?
    Non, un "callback" fait ce que l'appelant décide de lui faire faire.

    Par contre, mettre en place un callback en .net qui sera déclenché par du code natif est quelque peu compliqué à cause du Garbage Collector.

    Il y a quelques temps, j'ai écrit un tutoriel sur l'utilisation de ETW en .Net. On est confronté à la même problématique puisqu'il est nécessaire de mettre en place un callback qui sera appelé par Windows.
    Regarde le chapitre III-A (Le garbage collector n'est pas ton ami).

  9. #9
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2011
    Messages : 27
    Points : 19
    Points
    19
    Par défaut
    Je vais m'efforcer de répondre a chacun, tout d'abord la réponse de Paul a convaincu mon responsable de faire les requêtes simplement, quite a faire plus d’échange. Ce qui m'arrange et avec quoi je pourrais me débrouiller je pense .
    Andnotor, j'ai jeté qu'un coup d’œil rapide à opc cela me semble basé sur des objets COM et je sais que cette solution à était écarté par mes prédécesseur il y a longtemps déjà (e ne sais pas vraiment pourquoi, on a évoquer le fait que .net n'accepte que les COM rédigé en .NET ?!?! ).

    Franck, désolé mais je ne comprend pas ce que tu veux dire. Encore une fois peut être que je n'ai pas compris le fonctionnement d'une callback, mais pour moi:
    - je met en place une callback dans le .net qui appel une fonction dans la dll (asynchrone)
    - mon programme .net continue de tourner pendant que la fonction de la dll s’exécute
    - seulement quand la fonction de la dll se fini, le traitement dans la callback du coté .net s’exécute, toujours pendant que le reste du programme .net tourne.
    - quand le traitement de la callback est fini le pseudo thread créé pour l'appel asynchrone est détruit.

    bon ce dernier point est pour ma culture personnelle, j'ai l'impression de rater quelque chose .

    En tout cas merci de vos explications et de votre aide. .

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 256
    Points
    25 256
    Par défaut
    le Point important que j'ai l'impression que tu manques c'est que ton Exe.NET passe un pointeur de fonction pour le CallBack et que manuellement dans la DLL, tu utilises de pointeur de fonction et que tu appelles la fonction avec les paramètres nécessaires

    je t'invite à lire le code de ma fonction CallCmd

    Dans ton cas, CallCmd serait l'équivalent de la fonction de la DLL.
    CallCmd prend un paramètre un CallBack WaitEvent du type TCallCmdEvent
    Tu noteras que WaitEvent est appelé au sein d'une boucle (donc plusieurs fois)

    En gros le Code de la DLL, pourrait ressembler à cela !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    type
      TDLLFunctionEventType = (etStart, etProgress, etEnd, etError);
      TDLLFunctionEvent = procedure(EventNum: TDLLFunctionEventType; EventData: Pointer; CallBackContext: Pointer); stdcall;
      PDLLFunctionEventProgressData = ^TDLLFunctionEventProgressData;
      TDLLFunctionEventProgressData = record
        Iteration: Cardinal;
        DataSent: Cardinal;
        DataReceived: Cardinal; 
      end;
     
    procedure DLLFunction(Param: TParam; CallBackProc: TDLLFunctionEvent = nil; CallBackContext: Pointer = nil); stdcall;
    begin
      TThreadDLLFunction.Create(Param, CallBackProc, CallBackContext);
    end;
     
    constructor TThreadDLLFunction.Create(AParam: TParam; ACallBackProc: TDLLFunctionEvent; ACallBackContext: Pointer);
    begin
      inherited Create(false);
      FreeOnTerminate := true;
     
      FParam := AParam;
      FCallBackProc := ACallBackProc;
      FCallBackContext := ACallBackContext;    
    end;
     
    procedure TThreadDLLFunction.Execute();
    var
      Progression: TDLLFunctionEventProgressData;
      RobotWorking: Boolean;
      ResIO : Cardinal;
      DataDuRobot: Pointer;
      RobotError : Cardinal;
    begin
      if Assigned(FCallBackProc) then
        FCallBackProc(etStart, nil, FCallBackContext);
     
      Progression.Iteration := 0;
      Progression.DataSent := 0;
      Progression.DataReceived := 0;
     
      RobotWorking := RobotInit();
     
      while RobotWorking do
      begin
        Inc(Progression.Iteration);
     
        ResIO := ParleAuRobot(BlaBlaBla ...);
        if (ResIO > 0)
        begin
          Inc(Progression.DataSent, ResIO);      
          if Assigned(FCallBackProc) then
            FCallBackProc(etProgress, @Progression, FCallBackContext);
     
          ResIO := RobotRepondMoi(DataDuRobot);
          if (ResIO > 0)
          begin
            RobotWork := AnalyseReponseDuRobot(DataDuRobot);          
     
            Inc(Progression.DataReceived, ResIO);      
            if Assigned(FCallBackProc) then
              FCallBackProc(etProgress, @Progression, FCallBackContext);
          end
          else
          begin
            RobotWork := false;
     
            if Assigned(FCallBackProc) then
            begin
              RobotError := GetLastRobotError();
              FCallBackProc(etError, @RobotError, FCallBackContext);
            end;  
          end;
        end
        else
        begin
          RobotWork := false;
     
          if Assigned(FCallBackProc) then
          begin
            RobotError := GetLastRobotError();
            FCallBackProc(etError, @RobotError, FCallBackContext);
          end;       
        end;  
      end;
     
      RobotFinalize();
     
      if Assigned(FCallBackProc) then
        FCallBackProc(etEnd, nil, FCallBackContext);
    end;
    le code .NET serait un truc du genre

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    void RobotEventHandler(TDLLFunctionEventType EventNum, void* EventData, void* CallBackContext)
    {
      MonObjet = (TMonObjet)CallBackContext; 
      switch (EventNum)
      {
        case etStart: 
          MonObjet->AfficheRobotADemarré();
        break;
     
        case etProgress:       
          MonObjet->AfficheRobotProgression(
            ((PDLLFunctionEventProgressData)EventData)->DataSent,
            ((PDLLFunctionEventProgressData)EventData)->DataReceived);
        break;
     
        case etEnd:
          MonObjet->AfficheRobotATerminé();
        break;
     
        case etError: 
          MonObjet->AfficheRobotAEchoué((unsigned)*EventData);
        break;
     
      }
    }

    J'ignore ton protocol, mais avec un échange type TCP\IP ou un Port de communication genre COM ou USB, c'est tout à fait envisageable comme méthode !

  11. #11
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 451
    Points
    28 451
    Par défaut
    Citation Envoyé par titou640 Voir le message
    Je vais m'efforcer de répondre a chacun, tout d'abord la réponse de Paul a convaincu mon responsable de faire les requêtes simplement, quite a faire plus d’échange. Ce qui m'arrange et avec quoi je pourrais me débrouiller je pense .
    dans mes prestations il y aussi le conseil et l'audit de code

    pour ce qui est de la "callback", techniquement c'est juste une fonction passée en paramètre d'une autre. cela ne présume en rien de son usage.

    Dans l'API Windows tu as une série de fonction d'énumération qui utilisent une callback pour retourner chaque élément, et une fois la liste terminée, la callback n'est plus utilisée.

    Mais dans le cas de ta DLL, elle pourrait très bien stocker la fonction callback dans une variable globale pour la réutiliser plus tard...exactement comme on le fait avec les évènements. Quand tu définis un OnClick, il reste valable tout le temps; ta DLL pourrait définir une fonction procedure SetOnData(OnData: TCallBack) pour fixer la CallBack, et quand la DLL désire notifier d'un changement d'état du robot, elle appelle OnData...avec tous les problèmes de synchro que ça implique

  12. #12
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Citation Envoyé par titou640 Voir le message
    Franck, désolé mais je ne comprend pas ce que tu veux dire. Encore une fois peut être que je n'ai pas compris le fonctionnement d'une callback, mais pour moi:
    - je met en place une callback dans le .net qui appel une fonction dans la dll (asynchrone)
    - mon programme .net continue de tourner pendant que la fonction de la dll s’exécute
    - seulement quand la fonction de la dll se fini, le traitement dans la callback du coté .net s’exécute, toujours pendant que le reste du programme .net tourne.
    - quand le traitement de la callback est fini le pseudo thread créé pour l'appel asynchrone est détruit.
    Je ne suis pas sûr qu'on parle de la même chose.

    Je te parle plutôt du fonctionnement suivant :
    - Tu appelles une fonction dans la dll en lui fournissant en paramètre l'adresse d'une méthode (un délégué) qui devra être appellée lorsque le traitement sera terminé.
    - L'appli .net continue son exécution.
    - Lorsque le traitement lancé par la DLL a terminé, cette dernière appelle la méthode que tu lui a fournit en callback pour indiquer que le traitement est terminé.

    La DLL est du code natif.
    La méthode callback a exécuter est du code managé. Entre les deux, il faut convertir les appels. L'appel à la DLL est gérée automatiquement avec DllImport.
    En revanche, le rappel dans l'autre sens doit passer par un délégué : La DLL ne peut pas appeler le code managé directement. Le délégué est une classe intermédiaire créée par le compilateur .Net. La DLL fera son callback sur une fonction de cette classe. Cette dernière effectura la traduction code natif/code managé pour appeler à son tour la méthode .Net que tu voulais utiliser en callback.
    Ce que j'explique dans mon tutoriel, c'est que le délégué est lui même un objet managé qui risque d'être collecté par le GC entre l'appel de la DLL et le rappel en callback...

  13. #13
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2011
    Messages : 27
    Points : 19
    Points
    19
    Par défaut
    Okay, je comprend mieux maintenant , ce que j'appelais callback était l'échange de traitement entre la dll et le .net en général (comme une passerelle entre les 2 monde) , alors que c'est uniquement le traitement(pour mon cas '.net') post traitement 'dll'.
    Merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 40
    Dernier message: 21/06/2007, 17h58
  2. Réponses: 22
    Dernier message: 11/06/2007, 23h24
  3. Réponses: 4
    Dernier message: 11/04/2007, 12h49
  4. Réponses: 4
    Dernier message: 01/06/2006, 15h55
  5. [MFC][DLL]Dialog Avec ActiveX dans une DLL ?
    Par matazz dans le forum MFC
    Réponses: 1
    Dernier message: 16/05/2005, 16h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo