Freigeben über


Verwenden von C++-Interop (implizites PInvoke)

Im Gegensatz zu anderen .NET-Sprachen bietet Visual C++ Interoperabilitätsunterstützung, die verwalteten und nicht verwalteten Code in derselben Anwendung und sogar in derselben Datei (mit verwalteten , nicht verwalteten Pragmen) vorhanden ist. Auf diese Weise können Visual C++-Entwickler .NET-Funktionalität in vorhandene Visual C++-Anwendungen integrieren, ohne den Rest der Anwendung zu beeinträchtigen.

Sie können auch nicht verwaltete Funktionen aus einem verwalteten Compiland mithilfe von dllexport, dllimport aufrufen.

Implizites PInvoke ist sinnvoll, wenn Sie das Marshalling von Funktionsparametern oder andere Details, die bei einem expliziten Aufruf von DllImportAttribute angegeben werden können, nicht festlegen müssen.

Visual C++ bietet zwei Möglichkeiten für die Interoperation von verwalteten und nicht verwalteten Funktionen:

Explizites PInvoke wird von .NET Framework unterstützt und ist in den meisten .NET-Sprachen verfügbar. Doch wie der Name schon sagt, ist C++-Interop Visual C++-spezifisch.

C++ Interop

C++ Interop bietet eine bessere Typsicherheit und ist in der Regel weniger mühsam zu implementieren. C++-Interop ist jedoch keine Option, wenn der nicht verwaltete Quellcode nicht verfügbar ist oder für plattformübergreifende Projekte.

C++-COM-Interop

Die von Visual C++ unterstützten Interoperabilitätsfunktionen bieten einen besonderen Vorteil gegenüber anderen .NET-Sprachen, wenn es um die Interoperation mit COM-Komponenten geht. Anstatt auf die Einschränkungen des .NET Framework Tlbimp.exe (Type Library Importer) beschränkt zu sein, z. B. eingeschränkte Unterstützung für Datentypen und die obligatorische Gefährdung jedes Mitglieds jeder COM-Schnittstelle, ermöglicht C++ Interop com-Komponenten den Zugriff auf com-Komponenten zu Willen und erfordert keine separaten Interopassemblys. Im Gegensatz zu Visual Basic und C# kann Visual C++ COM-Objekte direkt mithilfe der üblichen COM-Mechanismen (z . B. CoCreateInstance und QueryInterface) verwenden. Dies ist aufgrund von C++-Interopfeatures möglich, die dazu führen, dass der Compiler den Übergangscode automatisch einfügt, um von verwalteten zu nicht verwalteten Funktionen und wieder zurück zu wechseln.

Mit C++-Interop können COM-Komponenten verwendet werden, wie sie normalerweise verwendet werden, oder sie können in C++-Klassen umschlossen werden. Diese Wrapperklassen werden als benutzerdefinierte aufrufbare Runtime-Wrapper oder CRCWs bezeichnet, und sie haben zwei Vorteile gegenüber der direkten Verwendung von COM im Anwendungscode:

  • Die resultierende Klasse kann aus anderen Sprachen als Visual C++ verwendet werden.

  • Die Details der COM-Schnittstelle können im verwalteten Clientcode ausgeblendet werden. .NET-Datentypen können anstelle von systemeigenen Typen verwendet werden, und die Details des Datenmarsings können transparent innerhalb des CRCW durchgeführt werden.

Unabhängig davon, ob COM direkt oder über ein CRCW verwendet wird, müssen andere Argumenttypen als einfache, blittbare Typen gemarstet werden.

Blitfähige Typen

Für nicht verwaltete APIs, die einfache, systeminterne Typen verwenden (siehe Blittable- und Nicht-Blittable-Typen), ist keine spezielle Codierung erforderlich, da diese Datentypen dieselbe Darstellung im Arbeitsspeicher aufweisen, aber komplexere Datentypen erfordern explizites Datenmarsing. Ein Beispiel finden Sie unter How to: Call Native DLLs from Managed Code Using PInvoke.

Beispiel

// 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

In diesem Abschnitt

Informationen zur Verwendung von Delegaten in einem Interoperabilitätsszenario finden Sie unter Delegaten (C++-Komponentenerweiterungen).

Siehe auch