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 :

Mixer natif et managé en C++/CLI


Sujet :

C++/CLI

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Mixer natif et managé en C++/CLI
    Bonjour,
    Sous Visual Studio 2010, j'ai créé un projet C++/CLI qui comporte deux classes : l'une managée, l'autre native, respectivement MUCam et NCam.


    La classe managée (MUCam.h) déclare un objet de la classe native NCam de la façon suivante : private: NCam * Cam;

    1 - une méthode "A" de la classe managée crée l'instance Cam : Cam = &NCam( ref );
    2 - et retourne la valeur de la méthode Statut de NCam : return = Cam->Statut();
    3 - je constate que le destructeur ~NCam(void) est appelé lors de cette instruction return, AVANT l'appel à la méthode Statut(). Ce qui signifie aussi que l'objet Cam n'est plus utilisable par la suite :

    Questions :
    1 - Est-il correct de procéder de cette façon en faisant cohabiter les deux classes dans le même projet C++/CLI ?
    2 - Si oui, pourquoi le destructeur est-il appelé à cet instant dans la méthode "A" ?
    3 - Comment instancier et utiliser un objet natif dans une classe managée en C++/CLI ? J'avais cru comprendre que ce langage permettait de faire cohabiter les deux mondes...

    J'espère avoir été assez clair.
    Merci de vos réponses.
    Cordialement

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

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Pouvez-vous nous donner la pile d'appel lors de l'appel au destructeur de Cam ?

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Bien volontiers.

    La méthode d'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    bool MUCam::OpenCamera(unsigned int camera)
    {
    	Cam = &NCam(camera);
    	return Cam->Statut();
    }
    La pile d'appel lors du breakpoint sur le destructeur de Cam :

     	UCamClr.dll!NCam::~NCam() Line 50	C++
    	UCamClr.dll!MUCam::OpenCamera(unsigned int camera) Line 173	C++
     	Test.exe!Test.Form1.Test_Click(object sender, System.EventArgs e) Line 57 + 0x1a bytes	C#
     	[External Code]	
     	Test.exe!Test.Program.Main() Line 18 + 0x1d bytes	C#
     	[External Code]	
    la ligne 173 est celle du return ci-dessus.

    Mais ai-je vraiment le droit d'inclure une classe native et une classe managée dans le même projet C++/CLI ?
    J'ai vu qu'il fallait développer un wrapper pour passer de l'un à l'autre...

    Merci de votre réponse
    Cordialement

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

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Heu, c'est pas plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cam = new NCam(camera);
    Mais ai-je vraiment le droit d'inclure une classe native et une classe managée dans le même projet C++/CLI ?
    C'est très vague votre question.
    Dans certain cas de figure oui, mais normalement, pas dans le votre.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Non, si j'écris : Cam = new NCam(camera);
    alors on passe deux fois dans le constructeur de la classe NCam ! Je ne m'explique pas pourquoi.

    Bon, je laisse tomber cette façon de faire avec deux classes.
    Je m'oriente vers l'écriture d'un Wrapper vrai. Les premiers essais sont concluants.

    Merci en tout cas d'avoir pris le temps de vous pencher sur cette question.
    Je note la discussion close.
    Cordialement

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Normalement, les wrappers C++/CLI sont bel et bien faits avec deux classes...

    Code C++/CLI : 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
    ref class MClass
    {
    	NClass* pNative;
     
    	MClass(/*paramètres*/)
    	{
    		pNative = new NClass(/*paramètres convertis*/);
    	}
    	//Finaliseur: Détruit ressources natives sans toucher à la moindre référence managée, qui peut être invalide
    	!MClass()
    	{
    		delete pNative, pNative=nullptr;
    	}
    	//Destructeur: Équivalent méthode IDisposable::Dispose(): Détruit ressources natives et managées.
    	~MClass()
    	{
    		//Détruire ressources managées puis appeler finaliseur
    		this->!Mclass();
    	}
     
    	void UneMethode() { pNative->UneMethode(); }
    };

    PS: Cam = &NCam(camera); est une horreur: Tu mémorises l'adresses d'un temporaire non-nommé! Tout aussi grave que retourner l'adresse d'une variable locale.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Merci Médinoc de votre réponse.
    Oui, je crois que c'est la bonne approche.
    J'ai voulu reprendre le problème à zéro. Je dispose en tout et pour tout d'une LIB statique, qui n'est pas une classe mais un ensemble de fonctions et déclarations (typedef).

    Dans un premier temps, pour en faire une classe C++ natif, je choisi de créer un nouveau projet pour construire une DLL MFC.
    Note : j'ai essayé une Library C++ mais elle est alors générée avec ref (donc managée).

    VS crée le projet dont voici le handler :

    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
    // NatCam.h : main header file for the NatCam DLL
    //
     
    #pragma once
     
    #ifndef __AFXWIN_H__
    	#error "include 'stdafx.h' before including this file for PCH"
    #endif
     
    #include "resource.h"		// main symbols
     
     
    // CNatCamApp
    // See NatCam.cpp for the implementation of this class
    //
     
    class CNatCamApp : public CWinApp
    {
    public:
    	CNatCamApp();
     
    // Overrides
    public:
    	virtual BOOL InitInstance();
     
    	DECLARE_MESSAGE_MAP()
    };
    Je vois que la classe créée hérite de CWinApp...

    Et ça commence par un message d'erreur : " 1 IntelliSense: #error directive: Please use the /MD switch for _AFXDLL builds c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\afxver_.h 81 3"

    Pouvez-vous m'aider ?
    Cordialement

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

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Ne mettez pas les MFC dans la boucle SVP.
    Pourquoi ne pas utiliser l'API C de la lib dans le code C++/CLI ?

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Dans cette LIB il y a des fonctions qui prennent un pointeur sur int, ou float (par exemple) en paramètre pour renvoyer une valeur.
    Je n'arrive pas à définir un wrapper avec une interface simple coté C#.

    par exemple :

    la LIB comporte une fonction :

    Comment écrire le wrapper managé pour cette fonction et comment l'appeler en C# ?
    J'ai réussi à le faire via un tableau mais je pense que ce n'est pas la bonne solution.

    Je me noie sans doute dans pas grand chose mais galère...
    Merci

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Regarde du côté des attributs DllImportAttribute et MarshalAsAttribute.

    Note: Si tu écris toi-même la DLL native, dans ce cas mon type préférentiel pour les tableaux c'est le SAFEARRAY utilisé par COM.

    PS: Si tu ne cherches pas spécifiquement à utiliser MFC, fais un "projet Win32" tout court, sans MFC, ça te permettra de faire une DLL "simple".
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Grand merci Médinoc pour cette piste que j'ai suivie.

    Voilà comment j'ai codé le wrapper de test pour cette fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool F1(int% max) { max = 2; return true; };
    et son appel en C#
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int test=0;
    Boolean sta = wrapper.F1(ref test);
    En sortie test vaux 2 et sta=true.

    L'appel réel de la LIB par le wrapper est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    bool F1(int% max)
    {
        int a;
        bool ok = LIB_F1( &a);
        max = a;
    return ok;
    }
    Cordialement

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Merci pour ce retour.

Discussions similaires

  1. Référence OCX depuis C++ natif (NON managé)
    Par cyrille37 dans le forum Débuter
    Réponses: 8
    Dernier message: 17/03/2010, 15h04
  2. mixer du MFC avec du c++/cli (voire avec C#)
    Par Axiome dans le forum Windows Forms
    Réponses: 3
    Dernier message: 19/01/2009, 17h38
  3. Réponses: 1
    Dernier message: 12/06/2006, 16h40
  4. [C#] Comment integrer dll C++ mixte managé/natif ?
    Par groskek dans le forum C++/CLI
    Réponses: 5
    Dernier message: 25/01/2006, 21h46

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