Traductor de C# a C++: Operaciones sobre el código fuente

A primera vista, puede parecer que el traductor solo tiene una forma de usarse: alimentándolo con código C#, esperamos obtener código C++ equivalente como salida. De hecho, esta forma es la más común, pero está lejos de ser la única. A continuación se presentan otros modos proporcionados por el marco de traducción de código y las utilidades relacionadas.

Análisis de código C# para su traducibilidad

Los productos son desarrollados por programadores que necesitan aprender los detalles del procedimiento de traducción de código a otros idiomas y las limitaciones asociadas con él. Como resultado, surgen situaciones en las que los cambios correctos desde el punto de vista de C# realizados por los desarrolladores del producto interrumpen el proceso de lanzamiento para otros idiomas.
Durante el desarrollo del proyecto, hemos intentado varias formas de automatizar la detección de tales problemas:

  1. El problema se puede detectar al traducir código C# a C++, construir el código C++ traducido o ejecutar pruebas. Este es el peor caso de los posibles, ya que los problemas se detectan después de fusionar el código en la rama principal, a menudo, antes del lanzamiento. Además, el problema lo resuelven personas que no están al tanto de los cambios que lo causaron, lo que aumenta el tiempo para eliminarlo.
  2. El problema se puede detectar en el entorno de CI. Por lo tanto, los desarrolladores de C# se enteran del problema antes de fusionarse en la rama común o después de tal fusión, dependiendo de las prácticas adoptadas por un equipo en particular. Esto aumenta la puntualidad en la resolución de problemas, pero requiere programar controles adicionales en la infraestructura del traductor o en utilidades de terceros.
  3. El problema se puede detectar localmente por el desarrollador de C# al ejecutar herramientas especializadas, por ejemplo, el traductor en modo analizador. Esto es conveniente, pero requiere el desarrollo de utilidades adicionales y disciplina.

Reducción de la versión del lenguaje C#

Limitar la versión del lenguaje C# requiere disciplina por parte de los programadores de C# y a menudo es inconveniente. Para sortear estas limitaciones, la traducción se puede realizar en dos etapas: primero, reemplazar las construcciones de las versiones modernas del lenguaje C# con análogos compatibles de estándares anteriores y luego proceder directamente a la traducción.
Al usar un traductor basado en un analizador obsoleto, la reducción solo se puede hacer usando herramientas externas (por ejemplo, utilidades escritas en base a Roslyn). Por otro lado, los traductores basados en Roslyn realizan ambas etapas secuencialmente, lo que permite usar el mismo código tanto al traducir código por ellos como al preparar código para la traducción por herramientas más antiguas.

Preparación de ejemplos de uso de bibliotecas convertidas

Esto es similar a traducir el código del producto, pero implica requisitos algo diferentes. Al traducir una biblioteca de decenas de millones de líneas, es importante, ante todo, seguir lo más estrictamente posible el comportamiento del código C# original, incluso a expensas de la legibilidad; el código más simple pero con efectos diferentes tendrá que depurarse más tiempo. Por otro lado, los ejemplos de uso del código traducido deben parecer lo más simples posible, dejando claro cómo usar el código en C++, incluso si no corresponde al comportamiento de los ejemplos originales escritos en C#.
Por ejemplo, al crear objetos temporales, los programadores de C# a menudo usan la declaración using para evitar fugas de recursos y establecer estrictamente el momento de su liberación, sin depender del GC. La traducción estricta de using da como resultado un código C++ bastante complejo debido a los muchos matices del tipo "si se lanza una excepción en el bloque de la declaración using y Dispose() también lanza una excepción, ¿cuál termina en el contexto de captura?". Tal código solo confundirá al programador de C++, creando la impresión de que usar la biblioteca es difícil, pero de hecho es suficiente tener un puntero inteligente en la pila, que en el momento adecuado elimina el objeto y libera los recursos.

Preparación de la documentación para el código

Las bibliotecas que proporcionan una API pueden documentarse a través de comentarios XML de acuerdo con las prácticas de C#. Transferir comentarios a C++, por ejemplo, en formato Doxygen, no es una tarea trivial. Además del marcado, es necesario reemplazar las referencias a tipos (ya que en C# los nombres completos se escriben con un punto, en C++ con un par de dos puntos), sus miembros y, en el caso de usar propiedades, también entender si es un getter o un setter. Además, traducir fragmentos de código que carecen de semántica y pueden estar incompletos.
Esta tarea se resuelve tanto por medio del propio traductor como por utilidades externas, por ejemplo, analizando la documentación XML generada y preparando adicionalmente fragmentos, como ejemplos de uso de métodos.

Conclusión

Como podemos ver, un marco profesional para la conversión de código, además de la traducción de alta calidad del código C# a C++, debería poder determinar la traducibilidad del código fuente, reducir la versión del lenguaje si es necesario, traducir ejemplos de uso de las bibliotecas convertidas y su documentación.

Artículos relacionados: