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

C++/CLI Discussion :

Lancer un event sans le connaître


Sujet :

C++/CLI

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 5
    Par défaut Lancer un event sans le connaître
    Bonjour à toutes et tous

    Je suis en train de faire un composant WPF (un poil de C# et beaucoup de C++/CLI) qui encapsule des librairie C++.

    Coté C++, nous avons un système de notification interne basé sur des callbacks. Je voudrais que ces notifications soient accessibles dans l'interface via l'envoi d'event managé classique (le but est que les utilisateurs du composant ne voient pas le code non managé)

    Sauf que j'aimerais éviter d'écrire un mécanisme générique auquel on file le type de notification, la classe d'argument de l'event CLI et qu'il transforme l'un en l'autre tout seul. Et je bloque sur deux points :
    - Pas le droit aux pointeurs de fonction sur une classe managée
    - Pas possible de déclaré un event depuis une classe non managé

    J'étais donc parti sur une classe template mais je n'arrive pas a utiliser un type d'event et/ou delegate en paramètre de template ... (ce qui me semble logique)
    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
     
    public ref class CkstClrKineoControl : public System::Windows::Controls::Control
    {
    public:
    	delegate void SelectionDidChangeDelegate(CkstClrNotificationSelection^ i_selection);
    	SelectionDidChangeDelegate^ SelectionDidChangeEvent;
    	event SelectionDidChangeDelegate^ SelectionDidChangeEventHandler
    	{...} // add, remove & raise
     
    private:
    	CkstClrNotificator<CkstClrNotificationSelection, SelectionDidChangeDelegate>* m_notificator;
    }
     
    CkstClrKineoControl::CkstClrKineoControl()
    {
    	m_notificator = new CkstClrNotificator <CkstClrNotificationSelection, SelectionDidChangeDelegate> (CkitNotificator::defaultNotificator(), CkppSelection::DID_CHANGE, SelectionDidChangeEvent);
    }
    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
     
    template < typename clrNotificationClass, typename eventClass >
    class CkstClrNotificator
    {
    public:
     
    	inline CkstClrNotificator(const CkitNotificatorShPtr& i_notificator, CkitNotification::TType i_type, eventClass^ i_event):
    		m_type(i_type),
    		m_event(i_event)
    	{
    		i_notificator->subscribe< CkstClrNotificator >(m_type, this, &CkstClrNotificator::notificationReciever);
    	}
     
    	inline virtual ~CkstClrNotificator()
    	{
    		CkitNotificator::defaultNotificator()->unsubscribe(m_type, this);
    	}
     
    	inline void notificationReciever(const CkitNotificationConstShPtr& i_notification)
    	{
    		CkstClrNotificationSelection^ clrSelection = gcnew clrNotificationClass(i_notification);
    		m_event->Invoke(clrSelection);
    	}
     
    private:
    	CkitNotification::TType m_type;
    	gcroot<eventClass^> m_event;
    };
    Bon ça marche pas, mais c'est le seul truc que j'arrive à faire compiler

    Donc je cherche soit a corriger cette méthode, soit une autre méthode ou je pourrais transformer mes notifications en event managé sans avoir a écrire une classe spécifique non managé et une fonction managé spécifique pour faire envoyé l'event, ceci par type de notification a envoyer

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 474
    Par défaut
    Je ne comprends pas tous à votre question.

    Vous mélangez le problème et votre solution.

    Pouvez-vous être plus précis sur le problème initial ?

    - Pas le droit aux pointeurs de fonction sur une classe managée
    Je suis très circonspect sur cette assertion.

    De plus un Event n'est qu'un multicast delegate habillé.

    Et avoir un pointeur sur un delegate c'est tout à fait possible :
    GetFunctionPointerForDelegate( http://msdn.microsoft.com/fr-fr/libr...rdelegate.aspx)

    Voici un exemple d'utilisation.
    http://www.codeguru.com/forum/showthread.php?t=444298

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 5
    Par défaut
    Merci de votre réponse. J'avais mélangé un peu de ma solution pour essayer d'expliquer ce que je voulais.

    Le but ultime est de branché des callback non managé sur des events, en un minimum de code.

    J'ai effectivement trouvé et utiliser le GetFunctionPointerForDelegate depusi mon dernier message (j'ai commencé le C++/CLI il y a 3 semaines ) mais ce n'est pas encore satisfaisant, parce que j'utilise un event classique (définition du delegué et de l'event), et une callback pour lancer l'event (donc une définition de délégué, un delegué et la fonction à appeler).
    Je voudrais éviter d'avoir à faire le second point vu que ça fait toujours la même chose, ça devrait pouvoir être écrit une fois pour toute et pas à chaque event

    Ma callback actuellement fait cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void CkstClrKineoControl::fireSelectionDidChange(const CkitNotificationConstShPtr& i_selection)
    {
    	CkstClrNotificationSelection^ clrNotification = gcnew CkstClrNotificationSelection(i_selection);
    	SelectionDidChangeEvent(clrNotification);
    };
    Ou
    - CkitNotificationConstShPtr est ma notification c++
    - CkstClrNotificationSelection est mon EventArgs de l'event SelectionDidChangeEvent

    Idéalement ça devrait pouvoir se faire sous forme template avec en paramètre :
    - La classe de l'EventArgs (qui prends toujours en constructeur un CkitNotificationConstShPtr)
    - L'event à envoyer

    Je n'arrive pas à lancer directement l'event depuis le code C++ non managé
    Et je n'arrive pas non plus à appeler un delegate qui prends en paramètre une classe managée (erreur à l’exécution)
    Par contre un délégué qui prends un void* que je cast ça marche

    Bref, j'ai loupé un truc sur le mixe Template + Event

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 474
    Par défaut
    Je ne vois toujours pas clairement le problème. Désolé.

    Mais voici un exemple d'appel d'un delegate depuis du code natif.
    http://tigerang.blogspot.com/2008/09...e-pinvoke.html

  5. #5
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 5
    Par défaut
    Citation Envoyé par bacelar Voir le message
    Je ne vois toujours pas clairement le problème. Désolé.

    Mais voici un exemple d'appel d'un delegate depuis du code natif.
    http://tigerang.blogspot.com/2008/09...e-pinvoke.html
    Ton exemple, comme les autres que j'ai trouvé, indique comment appelé un delegate qui prends en argument du code non managé. Hors les events que j'envois contiennent un paramêtre managé (c'est l'exemple que je met dans le premier post). J'ai un crash à l'exécution dans ce cas, au moment de la transition native->managé (que je n'ai pas avec la callback intermédiaire qui récupère du non managé et active l'event managé)

    Bref en plus condensé :
    Déjà les définitions que j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	// SelectionDidChangeDelegate Event
    	delegate void SelectionDidChangeDelegate(CkstClrNotificationSelection^ i_selection);
    	event SelectionDidChangeDelegate^ SelectionDidChangeEvent;
     
    	// SelectionDidChangeDelegate Launcher
    	delegate void FireSelectionDidChangeDelegate(const CkitNotificationConstShPtr& i_selection);
    	void fireSelectionDidChange(const CkitNotificationConstShPtr& i_selection);
    	FireSelectionDidChangeDelegate^								m_SelectionDidChangeDelegate;
    Quand je fais mon delegué sur ma callback intermédiaire j'utilise ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	m_SelectionDidChangeDelegate = gcnew FireSelectionDidChangeDelegate(this, &CkstClrKineoControl::fireSelectionDidChange);
    	System::IntPtr functor = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_SelectionDidChangeDelegate);
    	m_notificator = new CkstNotificator(CkitNotificator::defaultNotificator(), CkppSelection::DID_CHANGE, functor.ToPointer());
    (CkstNotificator appelle functor.ToPointer() quand il reçoit l'event interne DID_CHANGE)

    Comment passer directement l'event plutôt qu'une callback ?
    Je n'arrive pas/ne sais pas à accéder à "l'objet" Event à part ce que j'avais fait dans mon premier post, mais qui crash (et l'appel direct à Invoke me paraît bizarre)

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 474
    Par défaut
    Citation Envoyé par AMoreau_Kineo Voir le message
    Ton exemple, comme les autres que j'ai trouvé, indique comment appelé un delegate qui prends en argument du code non managé. Hors les events que j'envois contiennent un paramêtre managé (c'est l'exemple que je met dans le premier post). J'ai un crash à l'exécution dans ce cas, au moment de la transition native->managé (que je n'ai pas avec la callback intermédiaire qui récupère du non managé et active l'event managé)
    L'eventArg est managé mais rempli dans du code natif.
    The EventData is a data structure that shares the same binary layout as the one that will be created and marshaled from the native code.
    Avez-vous lu attentivement l'exemple ?

  7. #7
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 5
    Par défaut
    J'ai implémenter l'exemple, ça marche

    Ca marche même quand je rajoute un gcroot<CkstClrNotificationSelection^> dans la struct

    Sauf que je n'arrive pas a remplacer la struct par le gcroot<CkstClrNotificationSelection^> directement, Ca compile Mais à l'appel de fonction j'ai l'erreur suivante :

    Une exception non gérée du type 'System.Runtime.InteropServices.COMException' s'est produite dans Module inconnu.

    Informations supplémentaires*: Erreur non spécifiée (Exception de HRESULT : 0x80004005 (E_FAIL))
    C'est en ça que je disais que j'ai trouvé des exemples passant des arguments non managé (parce que dans l'exemple, on utilise une struct non managé, c'est coté managé qu'on spécifie les paramètres d'alignement mémoire pour que ça passe)

  8. #8
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 474
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 474
    Par défaut
    Je pense que votre problème est lié au fait que vous utilisez une référence d'objet managé comme un pointeur natif nu. Dans ce cas de figure, vous êtes obligé "d'épingler" la référence pour qu'elle ne bouge plus en mémoire.

    http://www.dotnetmonster.com/Uwe/For...ng-a-bridge-or

    Pourquoi ne pas passer par une structure contenant une référence managée ?Cela permet de ne pas "gérer" cet "épinglage".

  9. #9
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 5
    Par défaut
    (Au passage : merci de passer du temps à essayer de résoudre mon problème)

    A priori je ne dois pas avoir de problème d'épingalge, vu que je n'utilise pas de pointeur natif pour désigner un objet managé.

    l'event Args est crée par le code non-managé via un gcroot, envoyé à la callback, et oublié, mais après être sorti de la callback.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	inline void notificationReceiver(const CkitNotificationConstShPtr& i_notification)
    	{
    		gcroot<CkstClrNotificationSelection^> notification = gcnew CkstClrNotificationSelection(i_notification);
    		(*m_delegateFunctor)(notification);
    	}
    Ou alors c'est le delegate qu'il faut pin ?

    Sinon je n'utilise pas la structure parce que coté C#, il faut que l'event soit "propre" (que le client n'est pas a gérer une surcouche qui ne lui sert pas). Je préfère écrire ma callback intermédiaire en interne que d'ajouter une couche visible en externe

Discussions similaires

  1. [Système] Lancer un script sans attendre sa fin ?
    Par parisien dans le forum Langage
    Réponses: 9
    Dernier message: 03/11/2005, 22h09
  2. [Système] Lancer un executable sans attendre la fin
    Par raptor70 dans le forum Langage
    Réponses: 1
    Dernier message: 27/10/2005, 14h25
  3. Comment lancer une appli sans afficher ses fiches
    Par raoulmania dans le forum Langage
    Réponses: 5
    Dernier message: 02/09/2005, 18h07
  4. [CR8.5]lancer plusieurs impressions sans utiliser l'ocx
    Par sboober dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 04/05/2005, 10h08
  5. [MFC]dlg : lancer un dlg sans le montrer
    Par Tsunamis dans le forum MFC
    Réponses: 10
    Dernier message: 16/06/2004, 10h18

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