26 enero 2024
El diseño y desarrollo del traductor de código de C# a C++ se realizó exclusivamente por CodePorting. Requirió muchas investigaciones, la aplicación de múltiples enfoques y pruebas, diferenciándose por el modelo de memoria y otros aspectos. Al final, se eligieron dos soluciones. Una de ellas se utiliza actualmente para las versiones de C++ de los productos Aspose.
Ahora es el momento de explicar las tecnologías que utilizamos en el traductor de código. El traductor es una aplicación de consola escrita en C#, lo que facilita su integración en scripts que realizan secuencias típicas como traducir-compilar-probar. También hay un componente de GUI que te permite hacer lo mismo haciendo clic en los botones.
El análisis de sintaxis se realiza mediante la biblioteca NRefactory en la generación obsoleta del traductor y mediante Roslyn en la nueva.
El traductor utiliza varios recorridos de AST tree para recopilar información y generar código C++ de salida. Para el código C++, no se crea una representación AST; en su lugar, manejamos el código de salida en forma de texto puro.
En muchos casos, se requiere información adicional para ajustar el traductor. Esta información se pasa mediante opciones y atributos. Las opciones se aplican al proyecto completo. Por lo general, se utilizan para especificar el nombre de la macro de exportación de clases o los símbolos condicionales de C# utilizados al analizar el código. Los atributos se aplican a los tipos y entidades y proporcionan información específica para ellos, por ejemplo: marcar qué miembros de la clase requieren calificadores const
o mutable
en el código traducido o qué entidades deben excluirse de la traducción.
Las clases y estructuras de C# se convierten en clases de C++. Sus miembros y código fuente se traducen a análogos más cercanos. Los tipos y métodos genéricos se mapean a plantillas de C++. Las referencias de C# se traducen en punteros inteligentes (compartidos o débiles). Las clases de referencia se definen en la biblioteca. Otros detalles internos del traductor de código se describirán en un artículo aparte.
Por lo tanto, el proyecto traducido de C# a C++ depende de nuestra biblioteca en lugar de las bibliotecas .NET:
Para construir la biblioteca del traductor de código y los proyectos traducidos, utilizamos Cmake. Actualmente, ofrecemos soporte para los compiladores VS 2017 y 2019 (Windows), GCC y Clang (Linux).
Como ya se mencionó, la mayoría de nuestras implementaciones .NET son adaptadores delgados sobre bibliotecas de terceros, que incluyen:
Tanto el Traductor como la Biblioteca están cubiertos con numerosas pruebas. Las pruebas de la Biblioteca utilizan el marco de trabajo GoogleTest. Las pruebas del Traductor están escritas principalmente en NUnit/xUnit y se dividen en varias categorías, lo que garantiza que:
Utilizamos GitLab como sistema de control de versiones. Para la integración continua, utilizamos Jenkins. Los productos traducidos están disponibles como paquetes NuGet y archivos descargables.
Mientras trabajábamos en este proyecto, nos encontramos con varios problemas diferentes. Algunos de ellos eran esperados, mientras que otros surgieron en el camino:
Object
, y la mayoría de las clases de la biblioteca estándar no tienen RTTI (información de tipo en tiempo de ejecución). Esto hace imposible mapear los tipos de .NET a los de la STL (Standard Template Library) de C++.yield
).A pesar de todo esto, el proyecto de traducción de código es muy interesante desde un punto de vista técnico, y su complejidad académica nos obliga a aprender algo nuevo constantemente.
Mientras trabajábamos en el proyecto de traducción de código, logramos implementar un sistema que resuelve una interesante tarea académica de traducción de código. Hemos organizado lanzamientos mensuales de las bibliotecas Aspose para el lenguaje con el que no se suponía que debían funcionar.
Está previsto publicar más artículos sobre el traductor de código. El próximo artículo explicará el proceso de conversión en detalle, incluyendo cómo se mapean las construcciones concretas de C# a C++. Otro artículo tratará sobre el modelo de gestión de memoria.
Haremos nuestro mejor esfuerzo para responder a las preguntas que se nos hagan. Si los lectores están interesados en otros aspectos del desarrollo del traductor de código, podríamos considerar escribir más artículos al respecto.