C# zu C++ Übersetzer: Operationen mit dem Quellcode

Auf den ersten Blick mag es so aussehen, als hätte der Übersetzer nur eine Möglichkeit zur Verwendung: Indem wir ihm C#-Code zuführen, erwarten wir äquivalenten C++-Code als Ausgabe. Tatsächlich ist dies der häufigste Weg, aber bei weitem nicht der einzige. Im Folgenden sind weitere Modi aufgeführt, die vom Code-Übersetzungssystem und verwandten Dienstprogrammen bereitgestellt werden.

Analyse des C#-Codes auf Übersetzbarkeit

Produkte werden von Programmierern entwickelt, die die Details des Verfahrens zur Übersetzung von Code in andere Sprachen und die damit verbundenen Einschränkungen kennen müssen. Dadurch entstehen Situationen, in denen aus Sicht der C#-Entwickler vorgenommene Änderungen den Freigabeprozess für andere Sprachen beeinträchtigen.
Während der Projektentwicklung haben wir verschiedene Möglichkeiten ausprobiert, um die Erkennung solcher Probleme zu automatisieren:

  1. Das Problem kann beim Übersetzen von C#-Code in C++, beim Erstellen des übersetzten C++-Codes oder beim Ausführen von Tests erkannt werden. Dies ist der schlimmste Fall der möglichen, da Probleme nach dem Zusammenführen des Codes in den Hauptzweig oft vor dem Release erkannt werden. Außerdem wird das Problem von Personen gelöst, die sich der Änderungen, die es verursacht haben, nicht bewusst sind, was die Zeit zur Beseitigung verlängert.
  2. Das Problem kann in der CI-Umgebung erkannt werden. Auf diese Weise erfahren C#-Entwickler vor dem Zusammenführen in den gemeinsamen Zweig oder nach einem solchen Zusammenführen von dem Problem, abhängig von den von einem bestimmten Team praktizierten Verfahren. Dies erhöht die Aktualität der Problemlösung, erfordert jedoch zusätzliche Überprüfungen in der Übersetzerinfrastruktur oder von Drittanbieterdienstprogrammen.
  3. Das Problem kann lokal vom C#-Entwickler erkannt werden, wenn spezialisierte Tools ausgeführt werden, z. B. der Übersetzer im Analysemodus. Dies ist bequem, erfordert jedoch die Entwicklung zusätzlicher Dienstprogramme und Disziplin.

Herabsetzen der C#-Sprachversion

Die Begrenzung der C#-Sprachversion erfordert Disziplin von C#-Programmierern und ist oft umständlich. Um diese Einschränkungen zu umgehen, kann die Übersetzung in zwei Schritten erfolgen: Zuerst werden die Konstrukte moderner Versionen der C#-Sprache durch unterstützte Analoga aus vergangenen Standards ersetzt, und dann erfolgt die direkte Übersetzung.
Bei Verwendung eines Übersetzers auf Basis eines veralteten Parsers kann die Herabsetzung nur mithilfe externer Tools (z. B. Dienstprogramme, die auf Roslyn basieren) erfolgen. Andererseits führen Übersetzer auf Basis von Roslyn beide Schritte nacheinander aus, sodass derselbe Code sowohl beim Übersetzen durch sie als auch beim Vorbereiten des Codes für die Übersetzung durch ältere Tools verwendet werden kann.

Vorbereitung von Beispielen zur Verwendung konvertierter Bibliotheken

Dies ähnelt der Übersetzung von Produktcode, erfordert jedoch etwas unterschiedliche Anforderungen. Bei der Übersetzung einer Bibliothek mit zig Millionen Zeilen ist es wichtig, zunächst das Verhalten des ursprünglichen C#-Codes so genau wie möglich zu befolgen, selbst auf Kosten der Lesbarkeit – einfacher, aber unterschiedlicher Code muss länger debuggt werden. Andererseits sollten Beispiele zur Verwendung des übersetzten Codes so einfach wie möglich aussehen, um klarzustellen, wie der Code in C++ verwendet werden kann, auch wenn er nicht dem Verhalten der ursprünglichen Beispiele entspricht, die in C# geschrieben wurden.
Beispielweise verwenden C#-Programmierer beim Erstellen temporärer Objekte oft die using-Anweisung, um Ressourcenlecks zu vermeiden und den Zeitpunkt ihrer Freigabe strikt festzulegen, ohne sich auf den Garbage Collector zu verlassen. Eine strenge Übersetzung von “using” ergibt jedoch recht komplexen C++-Code aufgrund vieler Nuancen wie "Wenn eine Ausnahme im Block der using-Anweisung ausgelöst wird und Dispose() ebenfalls eine Ausnahme auslöst, welche gelangt in den Catching-Kontext?". Solcher Code könnte den C+±Programmierer irreführen und den Eindruck erwecken, dass die Verwendung der Bibliothek schwierig ist. Tatsächlich reicht es jedoch aus, einen intelligenten Zeiger auf dem Stack zu haben, der das Objekt zum richtigen Zeitpunkt löscht und die Ressourcen freigibt.

Vorbereitung der Dokumentation für den Code

Bibliotheken, die eine API bereitstellen, können gemäß C#-Praktiken durch XML-Kommentare dokumentiert werden. Die Übertragung von Kommentaren nach C++, beispielsweise im Doxygen-Format, ist keine triviale Aufgabe. Neben der Markierung müssen Verweise auf Typen ersetzt werden (da in C# vollständige Namen mit einem Punkt geschrieben werden und in C++ mit einem Doppelpunkt), ihre Mitglieder und im Fall von Eigenschaften muss auch verstanden werden, ob es sich um einen Getter oder einen Setter handelt. Darüber hinaus sollten Codefragmente übersetzt werden, die keine Semantik haben und unvollständig sein können.
Diese Aufgabe wird sowohl durch die Mittel des Übersetzers selbst als auch durch externe Dienstprogramme gelöst, z. B. durch die Analyse der generierten XML-Dokumentation und die zusätzliche Vorbereitung von Fragmenten wie Beispielen zur Verwendung von Methoden.

Fazit

Wie wir sehen können, sollte ein professionelles Framework für die Codekonvertierung neben einer hochwertigen Übersetzung von C#-Code nach C++ auch in der Lage sein, die Übersetzbarkeit des Quellcodes zu bestimmen, die Sprachversion gegebenenfalls herabzusetzen und Beispiele zur Verwendung der konvertierten Bibliotheken sowie deren Dokumentation zu übersetzen.

In Verbindung stehende Artikel