Problem bei der Verwendung von C++ Klassen in C#



  • Hallo,

    seit einigen Stunden nun versuche ich schon vergeblich meine in C++ geschriebenen Klassen in C# zu nutzen. Ich habe mir einige Tutorials durchgelesen bzw. angesehen, und habe auch Teilerfoge einfahren können. Allerdings funktioniert das Ganze nicht so wie ich es möchte.

    Mein Ziel ist es, die in C++ geschriebenen Klassen in C# zu nutzen, um dort eine graphische Oberfläche für das Programm erstellen zu können. Nun ist das Problem, das ich es nicht schaffe, alle Methoden der Klassen in C# nutzen zu können.

    Mittlerweile habe ich die Klassen mittels Wrappern in C# eingebunden, die Methoden, die eine andere Klasse (also nicht z.B. int) als Rückgabewert haben, kann ich aber nicht verwenden.

    Ein Beispiel:
    Ich möchte mittels der Methode "getField(int index)" das Feld bekommen, welches den angegebenen Index besitzt. Die Methode gehört zur Wrapperklasse "ChessBoard" und soll ein "ChessField" zurückliefern.

    ChessLibary::ChessField ChessLibary::ChessBoard::getField(int index)
    {
    	return ChessLibary::ChessField(pBoard->fields[index].getType(), pBoard->fields[index].getIndex(), pBoard->fields[index].isWhite());
    }
    

    Kann mir irgendjemand helfen, ist zum verzweifeln... 😞

    Gruß Alex 👍



  • C# (sowie das .NET-Framework) können nur mit "managed code" direkt kommunizieren (Alternative: P/Invoke), d.h. die Klassen müssen mittels "ref" deklariert sein: Ref classes and structs (C++/CX)
    Dann hast du aber keine nativen C++-Klassen mehr (sondern eben sog. "managed code").

    Die Alternative besteht darin, entweder oben genanntes P/Invoke mittels nativer C-Schnittstelle zu benutzen (d.h. keine Klassen) oder aber eben eigene Wrapper-Klassen in C++/CLI zu erstellen, welche die Datentransformation zwischen C++ und C# durchführen.



  • Hallo Th69,

    danke erstmal für die Antwort. 😃

    Die Wrapperklassen sind ref-Klassen, und somit "managed code".

    public ref class ChessBoard
    	{
    	public:
    		ChessBoard();
    		int doMove(Move m);
    		ChessLibary::ChessField getField(int index);
    

    Die unterste Methode funktioniert allerdings nicht, die Fehlermeldung:

    Error: class "ChessLibary::ChessField" has no suitable copy constructor

    Dabei ist es gar nicht meine Absicht den Copy Konstruktor aufzurufen, ich möchte einfach eine neue Instanz von ChessField erstellen. 😞



  • Kennst sonst jemand von euch eine Schritt für Schritt Erklärung, wie man C++ Code in C# verwenden kann?

    Oder würdet ihr einen anderen Weg für eine GUI für C++ Code empfehlen?

    Freue mich auf Antworten 🙂



  • Hallo Alex,

    wieso möchtest du keinen (Default-)Copy-Konstruktor für ChessField anbieten?
    Sobald du einen Wert über die Funktion zurückgibst wird der Copy-Konstruktor benötigt (mittels copy elision aber evtl. gar nicht effektiv so aufgerufen).

    Wenn du natives C++ verwendest, könntest du als GUI auch Qt o.ä. verwenden, s.a. [HOWTO] Welches Toolkit für GUIS?



  • Hallo,

    ehrlich gesagt ist es mir egal, ob ich einen Copy-Konstruktor anbiete oder nicht, wenn der Code funktioniert. 😉
    Auch nach sehr vielen Versuchen mit einigen Internetsuchen habe ich es nicht geschafft, einen Copy-Konstruktor in C++/CLI zu erstellen.

    Versuche wie

    ChessField(ChessField &cf);
    

    scheiterten, da es mir nicht erlaubt war, eine Referenz auf eine "C++/CLI ref class" zu erstellen.
    Das hier

    ChessField(ChessField% cf);
    

    gibt zwar keinen Fehler, macht aber glaube ich auch nicht das was ich will (kenn mich mit C++/CLI so gut wwie gar nicht aus 😕 ).

    Auch interessant:

    namespace ChessLibary {
    	public ref class ChessBoard
    	{
    	public:
    		ChessBoard();
    		ChessField getField(int index);
    

    soweit alles in Ordnung...

    ChessLibary::ChessField ChessLibary::ChessBoard::getField(int index)
    {
    	return ChessField();
    }
    

    ... hier dann wieder die Fehlermeldung, dass ein "suitable copy constructor" nicht vorhanden ist. 😡

    Wie kann ich das Problem lösen? 😕

    Gruß Alex 👍



  • Wenn du willst dass ChessField in der CLI Welt ein Reference-Type ist, dann lass die Methode eine Referenz zurückgeben, also ChessField^ .

    Wenn du willst dass ChessField in der CLI Welt ein Value-Type ist, dann definiere ChessField mit dem value Keyword statt ref ( value class oder besser gleich value struct ).

    => C++/CLI Grundlagen lernen, lernen, popernen 😉



  • Hallo,

    danke hustbaer, danke Th69!
    Irgendwie habe ich es jetzt hinbekommen (geht bestimmt einfacher, schneller etc.)! 😃

    Hat man gerade ein Problem (mit eurer Hilfe) gelöst, taucht das nächste auf... 😡

    Ich habe mich heute etwas intensiver mit C++/CLI beschäftigt, bin aber ratlos:

    Diese (eigentlich recht simple) Methode

    int ChessKI::generateMoves(ChessBoard %board, ChessField field)
    {
    	return pKI->generateMoves(*board.pBoard, (*board.pBoard).fields[field.getIndex()]);
    }
    

    macht Probleme. Denn zwar klappt das Compilieren ohne Probleme, doch bei der Einbindung in das C#-Projekt hakt es...
    Dort zeigt Visual Studio mir dann an, die Methode ist

    not supported by the language

    Wieso taucht dieser Fehler auf??? 😕

    An dem % kann es nicht liegen, hatte ich auch ohne probiert, selber Fehler...



  • Sorry Leute, aber ich versteh C++/CLI einfach nicht... 😕 😕

    ChessMove ^ getLegalMove(int index)
    		{
    			return gcnew ChessMove(pBoard->getLegalMove(index));
    		}
    

    Warum tauchen hier Fehler wie

    Error C2143 syntax error: missing ';' before '^'

    oder

    Error C2334 unexpected token(s) preceding '{'; skipping apparent function body

    auf?? 😕

    Bislang habe ich es noch nicht geschafft, eine in C++/CLI deklarierte Klasse (z.B. ChessBoard, ChessMove) als Rückgabewert nutzen zu können. Ist das überhaupt möglich? 😮

    Vielen Dank schon mal im Voraus!! 🙂


Anmelden zum Antworten