2010-03-28 18 views
23

Ist es eine gute Idee, C++ und C# zu kombinieren oder gibt es unmittelbare Probleme?Kombinieren von C++ und C#

Ich habe eine Anwendung, die einige Teile C++ benötigt, und einige Teile C# (für erhöhte Effizienz). Was wäre der beste Weg, um eine native C++ - DLL in C# zu verwenden?

Antwort

25

Ja mit C# und C++ für Ihr Produkt ist sehr üblich und eine gute Idee.

Manchmal können Sie verwaltetes C++ verwenden. In diesem Fall können Sie Ihr verwaltetes C++ - Modul wie jedes andere .NET-Modul verwenden.

Normalerweise würden Sie alles tun, was Sie in C# können. Für die Teile, die Sie in C++ tun müssen, würden Sie normalerweise eine C++ DLL erstellen und dann diese DLL von C# aufrufen. Das Marshalling von Parametern erfolgt automatisch für Sie. Hier

ist ein Beispiel für eine C-Funktion in einer DLL in C# importieren:

[DllImport("user32", CharSet=CharSet.Auto, SetLastError=true)] 
internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount); 
+0

Ist das Werbung für .NET? Wie steht es um plattformübergreifende Kompatibilität, Verbindungsprobleme, Lernkurve usw.? –

+1

Lernkurve? Ich nehme an, Sie kennen die Grundlagen von C++ und C#, wenn Sie versuchen, Sprachen zu kombinieren. Plattform überqueren? Es ist offensichtlich, plattformübergreifenden Code in C++ zu schreiben ist viel schwieriger, aber möglich. Scheint sogar ein wenig einfacher, wenn es mit C# kombiniert wird - ein höherer Code kann entscheiden, welche C/C++ - Teile auf einer bestimmten Plattform geladen und verwendet werden sollen. – Harry

+0

@Harry: Ich werde deine Antwort akzeptieren, wenn du mir zeigst (z. B. C# an einem PIC arbeitest ;-) –

29

Die Frage ist klar, wie sein eigenen C++ Code zu seiner C# Lösung zu integrieren, nicht nur, was verwenden, um Attribut eine vorhandene Funktion von der Win32-API aufrufen. Selbst wenn die Antwort bereits akzeptiert wurde, denke ich, dass sie unvollständig ist, und Folgendes sollte zutreffen.

Ja, das ist in den Fällen üblich, in denen die Task schneller ausgeführt werden kann, weniger Ressourcen benötigt und in einigen Fällen auch auf Methoden zugreifen kann, die im .NET-Framework nicht verfügbar sind.

Wenn Ihr Ziel ist die Effizienz zu gewinnen ist es, Ihnen eine native unmanaged C++ Bibliothek codieren müssen, werden Sie einen neuen unmanaged C++ Projekt erstellen (das kompiliert als DLL-Bibliothek) in Visual Studio und Referenz diese Bibliothek von Ihrem C# -Projekt .

In Ihrem Fall scheint es, dass Sie eine nicht verwaltete C++ - Bibliothek schreiben, und Folgendes gilt.

Für alle unmittelbaren Probleme, die Sie über stellten, würde es Auswirkungen auf die Bereitstellung und die Verschleierung haben.

  • Bereitstellung: Beachten Sie, dass die C# DLLs Sie bauen auf jedem CPU laufen, beide 32 und 64-Bit, aber diese neue nativen und nicht verwaltete C++ Bibliothek Ihr Programm zwingen, entweder für 32 oder 64 spezifisch.

    Dies ist etwas, das Sie in Ihrem Visual Studio Configuration Manager konfigurieren, und wird bei der Kompilierung Zeit betreut werden, werden Sie AnyCPU für C# Baugruppen und für die neue unmanaged C++ Bibliothek, holen, die in sein Es ist ein eigenes Projekt, Sie werden haben, um von Win32 oder X64 zu wählen.

    So werden Sie jetzt 2-Setups haben, ist es Best Practice empfohlen getrennte Setups zu haben, eine für 32 und eine andere für 64 oder da 32bit Unterstützung sehr schnell sinkt, Sie auf 64bit konzentrieren konnte nur.

    Auch Ihre Bibliothek verweist möglicherweise auf die von Visual Studio zur Verfügung gestellte VC++ redistibutable, die Sie möglicherweise in Ihre Implementierung einbeziehen müssen. Obwohl einige Versionen auf vielen Betriebssystemen enthalten sind, habe ich festgestellt, dass sie selten dieselbe ist mit und es ist am besten, es mit Ihrer Anwendung bereitzustellen, um sicher zu sein. Wenn dieses Paket fehlt, verfügt der Zielcomputer im Eventviewer-> Anwendungsprotokoll über eine SideBySide-Ausnahme.

    Um eine Ausnahme zu erfassen und zu behandeln, die aus nicht verwaltetem Code ausgelöst wird, ist der einzige Catch, der funktioniert, der leere, der ohne Ausnahme in der Klammer nach catch(). Sie können also Ihre Aufrufe in nicht verwalteten Code einbinden, um alle nicht verwalteten Ausnahmen zu behandeln, die aus dem nicht verwalteten Code stammen. Wenn Sie einen .net-Typ wie catch (Exception) setzen, springt er einfach darüber. Die einzige Möglichkeit, eine nicht verwaltete Ausnahme abzufangen, befindet sich in verwaltetem Code in diesem Format.


    try 
    { 
     //call unmanaged code 
    } 
    catch 
    { 
     //handle unmanaged exception 
    } 

  • Obfuscation: Alle Methodenaufrufe von C# getan, die jetzt nicht verwalteten Code aufrufen wird nun von Umbenennung automatisch ausgeschlossen werden. Und auf der anderen Seite, , wenn Ihr nicht verwaltete C++ Bibliothek braucht Methoden aufrufen von Ihrer verwalteten Baugruppen, müssen diejenigen von Umbenennung ausgeschlossen werden, manuell, um sichtbar für die C++ Bibliothek zu rufen sie.

Wenn das, was Sie brauchen nur gut bekannte C++ Bibliotheken wie die Windows-diejenigen zu nennen ist, werden Sie nicht ein neuen unmanaged C++ Projekt erstellen müssen, nur mit den Tasten [DllImport()] in einer früheren Antwort vorgeschlagen Attribut. Und in diesem Fall können Sie bei dieser Referenz einen Blick http://www.pinvoke.net/

+0

* 'fangen und behandeln eine Ausnahme von nicht verwalteten Code geworfen '* - Ich denke, das muss umformuliert werden, fangen ohne Ausnahme Typ-Spezifikation bedeutet nur Ausnahmen zu fangen. Es gibt keinen einfachen Weg für eine bestimmte Behandlung, aber das Auffangen hält Ihre C# -Anwendung am Laufen ... Siehe auch [.net - Können Sie eine native Ausnahme im C# -Code abfangen? - Stapelüberlauf] (https://stackoverflow.com/questions/150544/can-you-catch-a-native-exception-in-c-sharp-code) und [CA2102: Nicht-CLSCompliant-Ausnahmen in allgemeinen Handlern abfangen] (https://msdn.microsoft.com/en-gb/bb264489.aspx) – Wolf

-2

Weitere Informationen über C# im Vergleich zu C++ Unterschiede und possibles Fragen zusammengefasst werden können:

  • C# ist eine interpretierte, wie Java. C++ wird zu nativer Binärdatei kompiliert. Das tragen einige Unterschiede, die in folgenden Punkten weiter erläutert werden.
  • Platform Kompatibilität: C#, wie interpretiert und ein Microsoft-Produkt, funktioniert es gut unter Windows, richtig unter Linux dank eines großen Projekts Mono, aber nicht so gut (oder gar nicht) auf anderen Plattformen (Android, IOS, andere .) Wenn Sie Software für Embedded schreiben wollen, wo es keine Unterstützung für ein Betriebssystem gibt, oder um ein Betriebssystem selbst zu schreiben, können Sie C# meistens nicht verwenden. C++ ist völlig plattformübergreifend, sobald Sie einen Compiler haben (was normalerweise der Fall ist).
  • Interpretierter Code ist normalerweise eine Größenordnung langsamer als Binärcode [1]. Deshalb wirst du C++ verlinkt benutzen.
  • Binary vs. intermediate code: Intermediate Code Arbeit an jedem Interpreter für eine bestimmte Architektur, C++ muss für jede Architektur neu kompiliert werden.
  • Lernkurve: Entwickler müssen mehrere Sprachen lernen, was die Lernzeit erhöht. Es ist auch schwieriger, Experten in beiden Sprachen zu finden.
  • IDE: Für C++ ist jeder Texteditor ausreichend, für C# benötigen Sie meist spezielle IDE.
  • Echtzeit: Es scheint schwierig, sich Echtzeitbedingungen mit C# vorzustellen.
  • Einige Qualitätszertifikate könnten mit C# -Code (kritische Software) nicht zu bekommen sein.

Ist es eine gute Idee, sie zu kombinieren?

Das hängt wahrscheinlich von Ihrem Projekt ab. Für große HMI-Entwicklung unter Windows wird dies wahrscheinlich Ihre Entwicklungszeit verbessern. Andere Softwareanforderungen können Sie jedoch nur auf C++ beschränken.


[1] ich viele Male gelesen, dass Code in einigen Fällen interpretiert ist sogar schneller als Binär-Code, ist dies aufgrund eines Missverständnis: Der Interpreter mehrere Funktionen zur Vereinfachung implementiert, so, wenn Sie anrufen (zB) sort() bezeichnet in Wirklichkeit eine binäre Implementierung dieser Funktion. Wenn diese Funktion gut optimiert ist, könnte die letzte Zeit schneller sein, aber nur, weil alle im Binärformat ausgeführt werden und die interpretierte Komponente minimal ist, verglichen mit der gesamten Zeit, die zum Sortieren benötigt wird. Auf der anderen Seite, wenn Sie eine vollständige Logik in beiden Sprachen codieren, wird die binäre Version immer deutlich schneller sein. Der Grund ist einfach: Ein Interpreter ist eine Binärdatei, die zusätzlich zu Ihrem Code das gesamte Sprachframework ausführt.

+1

Jit ist nicht das Gleiche wie interpretiert. Jit kann kompilieren, um Code zu bearbeiten. – tohava

+0

Selbst mit "vollständig kompiliertem" C#, was nicht der übliche Fall ist, sind die meisten Bestätigungen hier noch gültig. Nur dass es nicht interpretiert wird und der Unterschied zwischen Leistung ist nicht so groß. –