DLL en C++ standard utilisé par une IHM en C#/WPF

Résolu
BunoCS Messages postés 15475 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 22 juin 2009 à 21:56
BunoCS Messages postés 15475 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 6 juil. 2009 à 15:05
Amis de la communautés bonjour!

J'aimerais savoir comment, depuis une IHM faite en C#/WPF, appeler une classe C++ se trouvant dans une DLL?

Sur le web, je vois principalement 2 méthodes:

- P/Invoke et DllImport : dans tous les exemples que je trouve ce sont
des fonctions C qui sont appelées. Comment faire dans le cas de
plusieurs classes? Je ne vais pas faire l'énumération de l'API
complète, non?

- faire une classe Wrapper en C++ managé appelant ma classe en C++ non
managé. A priori, ceci ne fonctionne que si la DLL a été faite avec des
objets COM. Vrai? Sinon, comment faire exactement?


Je précise que la DLL ne contient que du C++ tout à fait standard.
D'avance, merci de vos retours (j'ai également posé la question sur CppFrance)

@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...

5 réponses

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
22 juin 2009 à 23:46
Salut, c'est possible via P/Invoke, on utilise l'attribut DllImport et la convention d'appel ThisCall . La principale difficulté c'est qu'il te faut au moins une fonction en C pour créer l'objet avec "new" et une autre pour détruire l'objet avec "delete". J'ai posté un exemple ici -> http://www.csharpfr.com/forum/sujet-UTILISATION-FONCTIONS-CLASSE-PARTIR-DLL-CPLUSPLUS-DANS-APPLICATION_1272276.aspx
3
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
24 juin 2009 à 04:45
- Effectivement il faut avoir accès au code source ou une petite dll supplémentaire en flat C juste pour instancier et détruire la classe ou se tourner vers le C++/CLI pour mixer du code natif et du code managé.

- Oui tu vas devoir écrire toutes les définitions P/Invoke des méthodes ( que tu souhaites utiliser ) de ta classe native.

- EXTERN_C permet d'eviter la décoration des noms de fonctions mais pour les méthodes contenues dans une classe j'ai jamais trouvé comment l'eviter. J'utilise DumpBin.exe qui se trouve soit dans le platforme SDK ( soit dans VS, je sais plus ) pour trouver le nom décoré.
3
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
22 juin 2009 à 23:53
Voilà l'exemple mis au propre :

// C++



#define EXTERN_C extern "C"
#define DLLEXPORT __declspec(dllexport)



class DLLEXPORT Device
{



private:



 HWND m_hWnd;



public:



 Device( HWND hWnd );
 ~Device( );



 BOOL Clear( UINT color );



};

EXTERN_C DLLEXPORT Device* CreateDevice( HWND hWnd )
{
 Device* pDevice = new Device( hWnd );
 return pDevice;
}



EXTERN_C DLLEXPORT void DestroyDevice( Device* pDevice )
{
 if ( pDevice != NULL )
 {
  delete pDevice;
  //pDevice = NULL;
 }
}



// C#



[ SuppressUnmanagedCodeSecurity ]
internal sealed class Device
{
    private const string DLL_NAME = @"GX.dll";



    [ DllImport( DLL_NAME, CallingConvention = CallingConvention.StdCall ) ]
    public static extern IntPtr CreateDevice( IntPtr hWnd );
    [ DllImport( DLL_NAME, CallingConvention = CallingConvention.StdCall ) ]
    public static extern void DestroyDevice( IntPtr pDevice );



    [ DllImport( DLL_NAME,
        CallingConvention = CallingConvention.ThisCall,
            EntryPoint = "
[mailto:?Clear@Device@@QAEHI@Z
?Clear@Device@@QAEHI@Z
]
" ) ]
    [ return: MarshalAs( UnmanagedType.Bool ) ]
    public static extern bool Clear( IntPtr pDevice, int color );
}
0
BunoCS Messages postés 15475 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 avril 2024 103
23 juin 2009 à 20:56
Ok merci, je vais regarder ça de plus près.
Quelques questions en attendant:
- pour ajouter les fonctions create() et destroy(), cela suppose que j'ai accès au code de la DLL, ce qui est effectivement le cas pour moi. Dans le cas contraire, la méthode P/Invoke ne peut donc pas s'appliquer?
- la fonction Clear() fait partie de la classe Device. Je dois donc lister toutes les fonctions de toutes mes classes dans le DllImport?
- comment fait-on pour connaître la décoration des fonctions?

NB: y'a des mots clés que je ne maitrise pas encore (sealed, MarshalAs). Je file me documenter..mais je reviendrais sûrement

@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
BunoCS Messages postés 15475 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 avril 2024 103
6 juil. 2009 à 15:05
Merci Lutinore, ça m'a bien aidé, même si le projet a fait qu'on utilise la solution du Wrapper...

@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
0
Rejoignez-nous