C++ Framework mit C# GUI-Code verbinden
-
Der Titel sagts eigentlich schon - ich möchte mein C++ Framework mit einer C# GUI testen. Testen heißt, ich will mir "nur" schnell eine GUI zusammenbauen, die weder besonders schön noch absolut Absturzsicher oder sonstwas ist. Nebenbei brauche ich eine kleine Anwendung um C# zu lernen (d.h praktisch anzuwenden was ich theoretisch schon weiß), daher ist meine Wahl auf eine C#-GUI gefallen.
Wie würdet ihr das angehen, es braucht ja einen gewissen glue-Code, um beides zu verheiraten. Meines Wissens gibts da folgende Möglichkeiten:
- Einen C-Wrapper für das Framework schreiben und den aus dem C#-Code "unsafe" aufrufen
- Einen C++/CLI Wrapper für das Framework schreiben, der dem C#-Code die nötige .NET Schnittstelle anbietet.
Was ist vorzuziehen?
-
Erübrigt sich die Frage nicht, wenn Dein Framework Objektorientiert ist?
-
Ganz klar C++/CLI, wenn du es speziell für .NET haben willst.
Planst du noch weitere Experimente mit anderen Plattformen/Sprachen, dann eher C.
-
µ schrieb:
Erübrigt sich die Frage nicht, wenn Dein Framework Objektorientiert ist?
Nein, warum? Ob ich die C++-Klassen, die die Schnittstelle meines Framework bilden, jetzt durch "managed C++/CLI"-Klassen wrappe oder durch structs + Funktionen in C, macht wohl keinen großen Unterschied.
-
Kommt meiner Meinung nach etwas darauf an, wie gross die Schnittstelle von diesem C++ Framework ist. Wenn sie eher klein ist und die Aufrufe grössere Aufgaben ausführen, heisst es gibt nicht viel Verkehr, dann würde ich eine C Schnittstelle und P/Invoke verwenden. Dazu brauchst du kein unsafe!
Sobald die Schnittstelle allerdings komplexer wird, sofort zu C++/CLI wechseln, wobei man sich hier aber auch keine Illusionen machen darf. C++/CLI heisst meistens trotzdem eine rechte Menge Arbeit an Wrapperklassen und co. Auch empfinde ich es persönlich oft etwas als Gefrickel. Aber man hat halt mehr Kontrolle, kann objektorientiert mit Destruktoren, virtuellen Methoden, etc. arbeiten und im allgemeinen ist die Performance eher besser.Grüssli
-
Die Schnittstelle besteht aus 3 nicht besonders großen Interface-Klassen, die der Client ansprechen muss, zwei verschiedenen Eventklassen, die er verarbeiten muss, sowie einer abstrakten Basisklasse, die im Grunde nur als Callback-Sammlung dient, für die er eine Implementierung bereitstellen muss. Also wirklich überschaubar. Ich hatte mir sowieso überlegt, zusätzlich zur C++-Schnittstelle einen C-Wrapper anzubieten, das dürfte nicht allzu umfangreich werden
-
Dann mach einen C-Wrapper.
Der grösste Nachteil eines C-Wrappers ist vermutlich, dass du in C# nochmal wrappen musst - bzw. halt mit den "unmanaged" Handles/... der C-Seite hantieren. Und natürlich die doofen "extern" Deklarationen schreiben.
Wenn es aber nur 3-4 Klassen sind, wird das weniger ins Gewicht fallen.
-
hustbaer schrieb:
Der grösste Nachteil eines C-Wrappers ist vermutlich, dass du in C# nochmal wrappen musst - bzw. halt mit den "unmanaged" Handles/... der C-Seite hantieren.
Das wirst du aber auch in C++/CLI nicht anders machen können. Wrappen muss man es immer. Und meistens muss man in den Wrapper-Klassen das Dispose-Pattern verwenden. Ob P/Invoke oder C++/CLI spielt dabei wirklich keine grosse Rolle.
hustbaer schrieb:
Und natürlich die doofen "extern" Deklarationen schreiben.
Und in C++/CLI musst vieles vom Marshaling selber machen, was vielfach in ein kleines Gefrickel endet. Zumindest ist das meine bisherige Erfahrung
Grüssli
-
pumuckl schrieb:
- Einen C-Wrapper für das Framework schreiben und den aus dem C#-Code "unsafe" aufrufen
- Einen C++/CLI Wrapper für das Framework schreiben, der dem C#-Code die nötige .NET Schnittstelle anbietet.
Was ist vorzuziehen?
Meiner Erfahrung nach wäre es vorzuziehen, gar keinen Wrapper zu schreiben. Besser einfach direkt den untersten Layer der entsprechenden Logik hinter ein C bzw. .NET basiertes Interface packen.
pumuckl schrieb:
Nebenbei brauche ich eine kleine Anwendung um C# zu lernen (d.h praktisch anzuwenden was ich theoretisch schon weiß), daher ist meine Wahl auf eine C#-GUI gefallen.
Ich weiß nicht ob du dich wirklich mit Interop und C++/CLI rumschlagen willst, wenn du mit .NET noch nicht soviel Erfahrung hast...
-
Dravere schrieb:
hustbaer schrieb:
Der grösste Nachteil eines C-Wrappers ist vermutlich, dass du in C# nochmal wrappen musst - bzw. halt mit den "unmanaged" Handles/... der C-Seite hantieren.
Das wirst du aber auch in C++/CLI nicht anders machen können. Wrappen muss man es immer.
Warum soll man in C++/CLI nochmals was wrappen? Man kan hier native C/C++ direkt verwenden.
Wenn es sich um Klassen in C++ handel, ist der einfachere und übersichtliche Weg auf jeden Fall C++/CLI...
-
Jochen Kalmbach schrieb:
Warum soll man in C++/CLI nochmals was wrappen? Man kan hier native C/C++ direkt verwenden.
Du kannst die C++ Klassen zwar in C++/CLI verwenden aber dann nicht in C#. Um sie in C# verwenden zu können, musst du einen Wrapper bauen.
Grüssli
-
Dravere schrieb:
Jochen Kalmbach schrieb:
Warum soll man in C++/CLI nochmals was wrappen? Man kan hier native C/C++ direkt verwenden.
Du kannst die C++ Klassen zwar in C++/CLI verwenden aber dann nicht in C#. Um sie in C# verwenden zu können, musst du einen Wrapper bauen.
Und genau davon würde ich abraten. Denn Effektiv verbringst du dann viel Zeit (und vor allem Nerven, das würd ich bei C++/CLI nicht unterschätzen) damit, deinen Wrapper zu bauen, nur damit du dann in C# irgendwelche Logik damit implementierst, die du genausogut gleich in C++/CLI bauen und einfach von C# aus verwenden hättest können. Vor allem: Wenn sich was an dem Code um den der Wrapper gewrapped ist ändert, musst du nicht nur den Wrapper anpassen, sondern auch den C# Code der ihn verwendet. Wenn du einfach die unterste Schicht deiner Logik direkt in C++/CLI implementierst, musst du nur die anpassen/erweitern...
Wrapper sind meiner Erfahrung nach selten (nie?) eine gute Idee. Bau dir lieber eine Bibkiothek, die genau die Funktionalität implementiert, die du in deiner Anwendung benötigst und nicht nur einfach ein Spiegelbild irgendeiner Library.
-
dot schrieb:
Wenn du einfach die unterste Schicht deiner Logik direkt in C++/CLI implementierst, musst du nur die anpassen/erweitern...
Vielleich thast Du ja die Frage nicht ganz verstanden, aber die C++ Klassen sind schon vorhanden... da ist nichts, was man neu machen müsste oder wollte...
-
Dravere schrieb:
Jochen Kalmbach schrieb:
Warum soll man in C++/CLI nochmals was wrappen? Man kan hier native C/C++ direkt verwenden.
Du kannst die C++ Klassen zwar in C++/CLI verwenden aber dann nicht in C#. Um sie in C# verwenden zu können, musst du einen Wrapper bauen.
Aber du musst mit C++/CLI nur einen Wrapper schreiben.
A: ein C++/CLI Wrapper um native C++ Klassen
B: ein C Wrapper um native C++ Klassen + noch ein C# Wrapper um die so entstandene C API
Was wird wohl im Normalfall weniger Aufwand sein?
Dravere schrieb:
Und in C++/CLI musst vieles vom Marshaling selber machen, was vielfach in ein kleines Gefrickel endet. Zumindest ist das meine bisherige Erfahrung
In C++ musst du gar kein Marshaling machen. Du schreibst einfach einen managed Wrapper um die native C++ Klassen, und fertig.
Oder meinst du jetzt so Sachen wie System.String <-> C-String? Das muss man machen, ja. Dafür kann man sich auch aussuchen wie es gemacht wird. Und es gibt ja Haufenweise Helper-Klassen die einem den Grossteil der Arbeit abnehmen.
-
Jochen Kalmbach schrieb:
dot schrieb:
Wenn du einfach die unterste Schicht deiner Logik direkt in C++/CLI implementierst, musst du nur die anpassen/erweitern...
Vielleich thast Du ja die Frage nicht ganz verstanden, aber die C++ Klassen sind schon vorhanden... da ist nichts, was man neu machen müsste oder wollte...
Wieso, wenn es C++ Klassen sind kann ich sie doch nicht einfach so in .NET verwenden!?
-
Im GOF wird der Adapter auch Wrapper genannt.
sind also die Patterns aus dem GOF Buch keine gute Idee?
-
David W schrieb:
sind also die Patterns aus dem GOF Buch keine gute Idee?
Hältst du Singleton für eine gute Idee? Das steht auch im GoF Buch...
Das GoF Buch ist trotzdem gut. Das Problem sind nicht die dort beschriebenen Pattern, sondern wie sie verwendet werden.
-
dot schrieb:
Wieso, wenn es C++ Klassen sind kann ich sie doch nicht einfach so in .NET verwenden!?
Dann hast Du noch nie C++/CLI gemacht... genau dafür ist die Sprache entworfen worden
-
dot schrieb:
David W schrieb:
sind also die Patterns aus dem GOF Buch keine gute Idee?
Hältst du Singleton für eine gute Idee?
Jup.
-
Jochen Kalmbach schrieb:
dot schrieb:
Wieso, wenn es C++ Klassen sind kann ich sie doch nicht einfach so in .NET verwenden!?
Dann hast Du noch nie C++/CLI gemacht... genau dafür ist die Sprache entworfen worden
Das hab ich natürlich schon, sonst würd ich hier doch nicht mitdiskutieren. Aber vielleicht gibts ja irgendwas ganz grundlegendes was ich nicht weiß. Könnte es tatsächlich einen Weg geben, wie ich eine native C++ Klasse nehmen kann und diese, ohne auch nur irgendwas an Code zu ändern/hinzuzufügen, direkt in .NET verwenden kann? I don't think so. Zumindest müsste ich eine ref class draus machen. Dann ist es aber keine C++ Klasse mehr...