Upload
nicodeme-favre
View
104
Download
0
Embed Size (px)
Citation preview
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.
• Sous .NET CF 2.0, il n’y a pas de C++/CLI
Managed Code vs Unmanaged code
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
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 : ModèleUnmanaged Code
CommandCInterface.dll Command.dll
Command.h Command.cpp
CommandCInterface.cpp
API.h
CommandCInterface.h
Managed Code
DeviceApp.exe CommandCSInterface.dll
Program.csCommandCSInterface.cs
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!
Questions…