8 Stimmen

Was sind die Situationen oder Vor- und Nachteile der Verwendung von C++/CLI gegenüber C#?

Ich habe mich schon eine Weile mit dem .NET CLR beschäftigt, und meine bevorzugte Sprache ist C#.

Bis vor Kurzem war mir nicht bewusst, dass C++/CLI "gemischte Modus" ausführbare Dateien erstellen kann, die in der Lage sind, nativen und verwalteten Code auszuführen.

Nun, da ich das weiß, habe ich mit einem anderen Entwicklerfreund über dieses Merkmal diskutiert und versucht herauszufinden, wann und wie diese Fähigkeit nützlich sein könnte.

Ich gehe davon aus, dass nativer Code die Fähigkeit hat, effizienter und leistungsstärker zu sein als verwalteter Code, jedoch auf Kosten zusätzlicher Entwicklungszeit.

In der Vergangenheit griff ich ausschließlich auf native C++-Bibliotheken zurück und verwendete Interop, um die Funktionalität zu nutzen, die ich in die native Bibliothek geschrieben hatte.

Ich sehe den Vorteil, keine zusätzliche Bibliothek benötigen zu müssen, frage mich aber, was die Vor- und Nachteile der Verwendung von C++/CLI gegenüber einer rein verwalteten ausführbaren Datei sind, die in C# erstellt wurde, oder einer solchen ausführbaren Datei, die Interop verwendet, um eine rein native C++-Bibliothek aufzurufen?

(Nebenbemerkung: Sind die Begriffe Interop/PInvoke austauschbar, da ich den Unterschied zwischen den Begriffen nicht verstehe, sondern sie einfach gleich verwendet habe?)

13voto

philsquared Punkte 22090

Mit C++/CLI können Sie im Wesentlichen drei Arten von Objekten erstellen:

  1. Verwaltete Typen. Diese werden sich letztendlich im Wesentlichen in die gleiche IL wie das entsprechende C# kompilieren. Es gibt hier keine Leistungsmöglichkeit.
  2. Native Typen. Kompiliert herunter zu nativem Code, als ob Sie direkt C++ verwendet hätten.
  3. Mixed-Mode-Typen. Diese kompilieren zu verwaltetem Code, erlauben es Ihnen aber auch, auf native Typen zu verweisen.

Sie könnten (3) als das Schreiben von C#-Code mit PInvoke-Code betrachten, um auf die nativen Sachen zuzugreifen - nur wird all der PInvoke-Code für Sie generiert.

Natürlich gibt es noch mehr dazu, sowie einige Einschränkungen - aber das sollte Ihnen eine Vorstellung davon geben, wie es nützlich ist.

Mit anderen Worten, es ist wirklich eine Klebstoffsprache. Obwohl Sie in C++/CLI vollständige Apps schreiben können, ist es normaler, die verwalteten und nativen Teile getrennt zu halten und C++/CLI zu nutzen, um die beiden sauberer zu verbinden als mit PInvoke.

Eine weitere häufige Verwendung ist die Erweiterung eines vorhandenen, nativen C++-Codebasis mit .Net-Bibliotheksaufrufen.

Seien Sie einfach vorsichtig, dass Sie Ihren Code gut partitionieren, da es manchmal recht subtil sein kann, Ihren reinen C++-Code transparent in IL zu kompilieren!

Zu Ihrer Randnotiz: PInvoke ist eine bestimmte Art von Interop. Interop gibt es auch in anderen Formen, wie z.B. COM-Interop. Tatsächlich ist PInvoke genauer gesagt eine Reihe von Sprachfunktionen, die die Interop mit nativem Code erleichtern.

3voto

Randolpho Punkte 54011

Ich habe in der Vergangenheit Managed C++ (den Vorläufer von C++/CLI in .NET 1.1) effektiv verwendet. Ich finde, dass es am besten funktioniert, wenn du eine native C- oder C++-Bibliothek in verwaltetem Code verwenden möchtest. Du könntest den gesamten Interop/PInvoke-Weg gehen, was zu hässlichem C#-Code und häufigen Marshalling-Problemen führt, oder du könntest einen verwalteten C++-Wrapper schreiben, wo C++/CLI wirklich glänzt.

Weil C++/CLI verwalteter Code ist, kannst du ihn auf normale Weise von C# (oder VB.NET, wenn du in diese Richtung tendierst) aufrufen, indem du einen Verweis auf die .DLL hinzufügst. Kein Marshalling, kein dllimport, nichts Verrücktes wie das. Einfach normale Projektverweise. Darüber hinaus erhältst du den Vorteil von statisch verknüpften Bibliotheken, wenn deine native Bibliothek so konzipiert ist, was eine Gute Sache ist.

2voto

Sam Harwell Punkte 94511

Phil Nash hat wirklich die wichtigen Dinge getroffen. Hier ist noch ein weiteres, das ich mehr als einmal getroffen habe und der Hauptgrund ist, warum ich in der Vergangenheit C++/CLI verwendet habe:

Einige Anwendungen werden durch das Überprüfen aller DLLs an einem bestimmten Speicherort auf exportierte Funktionen mit einem bestimmten Namen erweitert. In C# gibt es keine Möglichkeit, einen nativen C-Style-Export anzugeben, aber in C++/CLI können Sie dies tun. Ich erstelle ein "Wrapper" in C++/CLI, der die Methode exportiert, etwaige Übersetzungen von C-Strukturen in verwaltete Objekte handhabt und den Aufruf an eine in C# geschriebene Assembly weiterleitet.

1voto

Sheng Jiang 蒋晟 Punkte 14949

Es gibt bestimmte Typen, die für andere Sprachen nicht verfügbar sind, wie Vorlagen, const und das Tracking-Handle von Boxed-Valuetypen.

Vorlagen sind zur Kompilierzeit spezialisiert. Generics sind zur Laufzeit spezialisiert. Obwohl CLR Generics-Spezialisierungen für zukünftige Verwendung zwischenspeichern sollte (damit Sie jedes Mal dieselbe Liste erhalten, wenn Sie sie verwenden), gibt es dennoch einen Leistungsabfall jedes Mal, wenn eine Generics-Spezialisierung angefordert wird.

Ich weiß, dass andere Sprachen das const-Attribut verwerfen, aber die Überprüfung zur Kompilierzeit in Ihrem C++-Code ist besser als nichts.

Ein Typ wie int^ ermöglicht Ihnen den direkten Zugriff auf den Speicher im verwalteten Heap, ohne unnötiges Unboxing. Dies kann die Leistung verbessern, wenn Tracking-Handles von Boxed-Values an Funktionen übergeben werden, die ein Tracking-Handle erwarten, wie z.B. Console::WriteLine(Object^). Natürlich kann die vorzeitige Box-Initialisierung nicht vermieden werden. In anderen Sprachen können Sie die Referenz in einer Objektvariablen speichern und sie weitergeben, um das Unboxing zu vermeiden, aber Sie verlieren die Überprüfung des Typs zur Kompilierzeit.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X