Kommunikation zwischen C# und C++ – Eine Anleitung

Angenommen Sie haben die Anforderung, Ihre in C# geschriebene Anwendung mit einer C++-Anwendung kommunizieren zu lassen, um beispielsweise Sensordaten von einer Hardwarekomponente auszulesen. Dann können Sie für diese Kommunikation aus verschiedenen Möglichkeiten wählen. In diesem Artikel wollen wir uns die Integration eines COM-Servers ansehen. Dazu wird im Folgenden ein C++-basierter COM-Server aus einem C#-Client heraus angesprochen.

Symbolic image: zwei Hände an einem Tablet

Voraussetzungen

Um diesem Tutorial folgen zu können, benötigen Sie folgende Dinge:

  • Visual Studio 2019 oder eine neuere Version
  • Visual Studio Profil .NET Desktopentwicklung
  • Visual Studio Profil Desktopentwicklung mit C++

Die Profile können über den Visual Studio Installer ausgewählt und installiert werden.

Schritt-für-Schritt-Anleitung: Integration von einem C++-COM-Server mit einem C#-Client

Wichtig: Nähere Informationen finden Sie auch in diesem Github Repository.

Zusätzlich erstellen wir einen C++-Server:

Schritt 1: Erstellen Sie ein C++-ATL-Projekt mit Executable Datei (.exe) als Anwendungstyp.

Schritt 2: Bitte löschen Sie das Projekt ComServerPS.

Schritt 3: Mit der rechten Maustaste auf den Server klicken und eine neue Klasse (ComServerMgr) hinzufügen. Das Ergebnis sollte wie im Bild unten aussehen:

Screenshot COM-Server
Abbildung 1: Hinzufügen einer neuen neue Klasse (ComServerMgr)

Schritt 4: Im ComServerMgr.h die AddOne() Methodheader hinzufügen, damit wir diese in die Klasse einfügen können:

public:
	CComServerMgr()
	{
	}

DECLARE_REGISTRY_RESOURCEID(106)


BEGIN_COM_MAP(CComServerMgr)
	COM_INTERFACE_ENTRY(IComServerMgr)
	COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()



	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

public:
	STDMETHOD(AddOne)(int value, int* result);


};

OBJECT_ENTRY_AUTO(__uuidof(ComServerMgr), CComServerMgr)

Schritt 5: Im ComServerMgr.cpp die AddMethod() hinzufügen. Über jene wollen wir später den gegebenen Wert um eins hochzählen:

STDMETHODIMP CComServerMgr::AddOne(int value, int* result)
{
	int res = value + 1;
	if (result != nullptr)
	{
		*result = res;
		return S_OK;
	}

	return S_OK;
}

Schritt 6: In ComServer.idl die AddMethod() ebenfalls hinzufügen und sie somit bekannt machen:

Screenshot COM-Server
Abbildung 2: AddMethod() im ComServer.idl

Schritt 7: Das Projekt bauen. Anschließend auf der Festplatte in das Verzeichnis gehen, in dem der Quellcode liegt und dort das Unterverzeichnis Build auswählen. Dort sollte nun die ComServer.exe liegen. Nun die Eingabeaufforderung als Administrator öffnen und folgenden Befehl eingeben:

ComServer.exe /Regserver

Bitte beachten Sie, dass ComServer der Name des Projekts ist. Wenn z.B. das Projekt „HelloWorld“ heißt, dann müsstet der Befehl lauten: „HelloWorld.exe /Regserver“.

Jetzt fahren wir mit dem Erstellen des C#-Clients fort.

Der Ablauf ist einfacher, als für den COM-Server:

Schritt 1: Erstellen einer Konsolenanwendung.

Schritt 2: Den COM Verweis hinzufügen.

Screenshot COM-Server
Abbildung 3: COM Verweis hinzufügen

Schritt 3: Nach unten scrollen, bis der ComServerLib Verweis zu sehen ist:

Screenshot COM-Server
Abbildung 4: ComServerLib Verweis

Bitte beachten Sie, dass der Verweis ComServerLib heißt, weil wir das Server-Projekt ComServer genannt haben. Wenn z.B. das Projekt „HelloWorld“ heißt, würde der Verweis HelloWorldLib heißen.

Schritt 4: Folgenden Code hinzufügen, durch den der COM-Server beim Start der Konsolenapplikation instanziiert und anschließend die Zahl 3 übergeben wird.

    class Program
    {
        static void Main(string[] args)
        {
            IComServerMgr mgr = new ComServerMgr();
            var x = mgr.AddOne(3);

            Console.WriteLine("Hello World!");
        }
    }

Schritt 5: Um das besser nachvollziehen zu können, ist es auch möglich, den Code im Debug-Modus und mit einem Breakpoint zu starten. Die Ausführung wird dann an der entsprechenden Stelle stehen bleiben.

Code snippet
Abbildung 5: Code im Debug-Modus und mit einem Breakpoint starten

Zusammenfassung

Zugegeben, das Beispiel war sehr einfach, zeigt aber bereits, wie man eine Verbindung zwischen COM-Servern und C#-Anwendungen herstellen kann. Das ist gerade im Vorfeld von Legacy Anwendungen sehr nützlich, zu denen es leider selten Dokumentation mit einer Erläuterung des Vorgehens gibt.

Für Fragen kontaktieren Sie mich gerne unter liviu.sosu@zeiss.com.
Danke an Florian Seeleitner für seine hilfreiche Unterstützung.

Dieser Beitrag wurde verfasst von: