250 likes | 377 Views
Appels de fonctions natives sous C#. Proposition d’une architecture pour « wrapper » une classe native. Managed code vs Unmanaged code C++ (compilation, décoration, exportation) Fonctionnalités « interops » de .NET Architecture proposée Création des 4 projets Déploiement.
E N D
Appels de fonctions natives sous C# Proposition d’une architecture pour « wrapper » une classe native
Managed code vs Unmanaged code • C++ (compilation, décoration, exportation) • Fonctionnalités « interops » de .NET • Architecture proposée • Création des 4 projets • Déploiement
Managed Code vs Unmanaged code • Managed code : code exécuter (interpréter) sous le « framework » .NET.
Managed Code vs Unmanaged code • Sous .NET CF 2.0, il n’y a pas de C++/CLI
C++: Compilation • Lors de la compilation, le compilateur génère un fichier .obj par fichier .cpp qu’il compile. • Toutes les fonctions et variables globales compilées dans un fichier .obj sont « marquées ». • Lors de l’application des liens, le « Linker » génère un fichier « PE » en liant tous les fichiers .obj.
C++: Décoration • La déclaration d’une fonction dans un fichier .obj est encodée (décorée). • L’algorithme de décoration dépend du compilateur (et parfois aussi de sa version). • En C, il n’y a habituellement pas de décoration.
C++: Décoration • Exemple: soit la variable globale« int dllVersion ». Son nom décoré sera« ?dllVersion@@3MA » sous Visual C++ 2005 • Pour déclarer, sous C++, une entité non décorée; il faut forcer le compilateur à l’interpréter comme du code C:extern ”C” int dllVersion;
C++: Exportation • Pour exporter une variable globale ou fonction, sa déclaration doit être ajoutée dans la table d’exportation du fichier « PE ». • « __declspec(dllexport) » le fait automatiquement.
C++: Exportation • Pour exporter une fonction non décorée:extern “C” __declspec(dllexport) void fnt(int);
Fonctionnalités « Interops » de .NET • P/invoke permet, sous .NET, d’exécuter du code natif (unmanaged). • Sous CF 2.0, la convention d’appel est __cdecl [DllImport("CommandCInterface.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, EntryPoint = "SetNameAgeCommand_SetNameAgeCommand_name_age")] internal static extern IntPtr SetNameAgeCommand_SetNameAgeCommand_name_age(byte[] name, Int32 age);
Architecture proposée : buts • Pouvoir simplement importer une classe sous C# qui fut implémentée sous C++ (unmanaged). • Apporter très peu de modifications au projet à importer. • Compréhensible et possiblement automatisable. • Simple à déployer.
Architecture proposée: projet « Command.dll » • Est un projet C++ unmanaged code. • Est le projet original à importer sous .NET • Nécessite très peu (ou pas du tout de modification).
Architecture proposée: CommandCInterface.dll • Est un projet C++ unmanaged code. • Est une interface C de la classe Command. • Pour chaque fonction membre de la classe « Command », il faut exporter une fonction « wrapper » • Il faut ajouter une référence au projet Command.dll • Exemple:extern "C" __declspec(dllexport) void SetNameAgeCommand_EncodeCommand(SetNameAgeCommand *this_);
Architecture proposée: CommandCSInterface.dll • Est un projet C#. • Est une interface C# de la classe Command. • Pour chacune des fonctions exportées de CommandCInterface.dll, il faut ajouter une fonction statique de type p/invoke. • Il faut ajouter une dépendance au projet CommandCInterface.dll.
Architecture proposée: CommandCSInterface.dll • La classe interface doit encapsuler un pointeur « protected IntPtr this_; » sur l’objet « Command ». Il doit être passé en paramètre lors de l’appel d’une fonction. • « this_ » est initialisé lors de la création d’une instance. • « this_ » est détruit lors de la destruction de l’instance.
Architecture proposée: CommandCSInterface.dll [DllImport("CommandCInterface.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, EntryPoint = "SetNameAgeCommand_EncodeCommand")] private static extern void SetNameAgeCommand_EncodeCommand(IntPtr p);
Architecture proposée: DeviceApp.exe • Est un projet C# • Utilise l’interface C# pour accéder à un objet de type « Command ». • Il faut ajouter une référence au projet CommandCSInterface.dll.
Création du projet Command.dll • C++, librairie pour Windows Mobile Device 5.0. • Réutiliser les mêmes fichiers utilisés pour compiler le projet sous Win32. • S’assurer d’être en « Unicode ».
Création du projet: CommandCInterface.dll • C++, librairie pour Windows Mobile Device 5.0. • S’assurer d’être en « Unicode ». • Ne pas oublier la référence sur Command.dll
Création du projet: CommandCSInterface.dll • C#, librairie 2.0 pour Windows Mobile Device 5.0. • Ne pas oublier la dépendance sur CommandCInterface.dll.
Création du projet: DeviceApp.exe • C# application graphique 2.0 pour Windows Mobile Device 5.0. • Ne pas oublier la référence sur CommandCSInterface.dll.
Déploiement • Il est important d’ajuster les propriétés des 4 projets concernant leur déploiement. • Tous les projets doivent être déployés dans le même répertoire!