Utilisation de l’interopérabilité C++ (PInvoke implicite)

Contrairement à d’autres langages .NET, Visual C++ prend en charge l’interopérabilité qui permet au code managé et non managé d’exister dans la même application et même dans le même fichier (avec les pragmas managés non managés ). Cela permet aux développeurs Visual C++ d’intégrer des fonctionnalités .NET dans des applications Visual C++ existantes sans déranger le reste de l’application.

Vous pouvez également appeler des fonctions non managées à partir d’une compilation managée à l’aide de dllexport, dllimport.

PInvoke implicite est utile quand vous n’avez pas besoin de spécifier la façon dont les paramètres de fonction seront marshalés, ou l’un des autres détails qui peuvent être spécifiés lors de l’appel explicite de DllImportAttribute.

Visual C++ fournit deux façons pour les fonctions managées et non managées d’interagir :

PInvoke explicite est pris en charge par le .NET Framework et est disponible dans la plupart des langages .NET. Mais comme son nom l’indique, L’interopérabilité C++ est spécifique à Visual C++.

Interopérabilité C++

L’interopérabilité C++ offre une meilleure sécurité de type et il est généralement moins fastidieux d’implémenter. Toutefois, L’interopérabilité C++ n’est pas une option si le code source non managé n’est pas disponible ou pour les projets multiplateformes.

interopérabilité C++ COM

Les fonctionnalités d’interopérabilité prises en charge par Visual C++ offrent un avantage particulier sur d’autres langages .NET lorsqu’il s’agit d’interagir avec les composants COM. Au lieu d’être limité aux restrictions de .NET Framework Tlbimp.exe (Importateur de bibliothèque de types), telles que la prise en charge limitée des types de données et l’exposition obligatoire de chaque membre de chaque interface COM, C++ Interop permet aux composants COM d’être accessibles à la volonté et ne nécessite pas d’assemblys d’interopérabilité distincts. Contrairement à Visual Basic et C#, Visual C++ peut utiliser des objets COM directement à l’aide des mécanismes COM habituels (tels que CoCreateInstance et QueryInterface). Cela est possible en raison des fonctionnalités d’interopérabilité C++ qui entraînent l’insertion automatique du code de transition entre les fonctions managées et les fonctions non managées, puis de nouveau.

À l’aide de l’interopérabilité C++, les composants COM peuvent être utilisés comme ils sont normalement utilisés ou ils peuvent être encapsulés dans des classes C++. Ces classes wrapper sont appelées wrappers pouvant être appelés wrappers pouvant être appelés runtime personnalisés, ou CRCWs, et ont deux avantages par rapport à l’utilisation de COM directement dans le code d’application :

  • La classe résultante peut être utilisée à partir de langages autres que Visual C++.

  • Les détails de l’interface COM peuvent être masqués dans le code client managé. Les types de données .NET peuvent être utilisés à la place de types natifs, et les détails du marshaling de données peuvent être effectués de manière transparente à l’intérieur du CRCW.

Indépendamment de l’utilisation directe ou directe de COM par le biais d’un CRCW, les types d’arguments autres que les types blittables simples doivent être marshalés.

Types blittables

Pour les API non managées qui utilisent des types intrinsèques simples (voir Types Blittable et non Blittable), aucun codage spécial n’est requis, car ces types de données ont la même représentation en mémoire, mais les types de données plus complexes nécessitent un marshaling de données explicite. Pour obtenir un exemple, consultez Guide pratique pour appeler des DLL natives à partir de code managé à l’aide de PInvoke.

Exemple

// vcmcppv2_impl_dllimp.cpp
// compile with: /clr:pure user32.lib
using namespace System::Runtime::InteropServices;

// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);

// explicit DLLImport needed here to use P/Invoke marshalling because
// System::String ^ is not the type of the first parameter to printf
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl,  CharSet = CharSet::Ansi)]
// or just
// [DllImport("msvcrt.dll")]
int printf(System::String ^, ...);

int main() {
   // (string literals are System::String by default)
   printf("Begin beep\n");
   MessageBeep(100000);
   printf("Done\n");
}
Begin beep
Done

Dans cette section

Pour plus d’informations sur l’utilisation de délégués dans un scénario d’interopérabilité, consultez délégué (extensions de composant C++).

Voir aussi