15 2월 2024
언뜻 보면 번역기가 이를 사용하는 방법은 한 가지뿐인 것처럼 보일 수 있습니다. 즉, C# 코드를 제공하면 동등한 C++ 코드를 출력으로 얻을 것으로 예상됩니다. 실제로 이 방법이 가장 일반적이지만 유일한 방법은 아닙니다. 다음은 코드 변환 프레임워크 및 관련 유틸리티에서 제공하는 다른 모드입니다.
프로그래머는 코드를 다른 언어로 번역하는 절차의 세부 사항과 이와 관련된 제한 사항을 학습해야 제품을 개발할 수 있습니다. 그 결과 제품 개발자가 C#을 올바르게 변경하면 다른 언어의 릴리스 프로세스가 중단되는 상황이 발생하기도 합니다.
프로젝트를 개발하는 동안 이러한 문제를 자동화하기 위해 여러 가지 방법을 시도했습니다:
C# 언어 버전을 제한하려면 C# 프로그래머의 규율이 필요하며 불편한 경우가 많습니다. 이러한 제한을 극복하기 위해 번역은 두 단계로 수행할 수 있습니다. 먼저 최신 버전의 C# 언어 구문을 과거 표준에서 지원되는 아날로그로 교체한 다음 바로 번역을 진행합니다.
오래된 파서를 기반으로 하는 번역기를 사용하는 경우 외부 도구(예: Roslyn을 기반으로 작성된 유틸리티)를 통해서만 낮추기를 수행할 수 있습니다. 반면에 Roslyn 기반 번역기는 두 단계를 순차적으로 수행하므로 코드를 번역할 때와 이전 도구로 번역할 코드를 준비할 때 모두 동일한 코드를 사용할 수 있습니다.
이는 제품 코드 번역과 유사하지만 다소 다른 요구 사항을 의미합니다. 수천만 줄의 라이브러리를 번역할 때는 우선 가독성을 희생하더라도 원본 C# 코드의 동작을 최대한 엄격하게 따르는 것이 중요하며, 더 간단하지만 다른 효과를 내는 코드는 디버깅 시간이 더 오래 걸릴 수 있습니다. 반면에 번역된 코드 사용 예제는 가능한 한 단순하게 작성하여 C#으로 작성된 원본 예제의 동작과 일치하지 않더라도 C++ 에서 코드를 사용하는 방법을 명확하게 보여 주어야 합니다.
예를 들어, 임시 객체를 만들 때 C# 프로그래머는 리소스 누수를 방지하고 GC에 의존하지 않고 릴리스 시점을 엄격하게 설정하기 위해 using 문을 사용하는 경우가 많습니다. using을 엄격하게 해석하면 "using
문 블록에서 예외가 발생하고 Dispose()
역시 예외를 발생시키면 어느 것이 캐치 컨텍스트에서 끝나는가?"와 같은 많은 뉘앙스가 있기 때문에 상당히 복잡한 C++ 코드가 됩니다. 이러한 코드는 C++ 프로그래머를 오도하여 라이브러리 사용이 어렵다는 인상을 주지만, 실제로는 스택에 스마트 포인터가 있으면 적절한 순간에 객체를 삭제하고 리소스를 해제하는 것으로 충분합니다.
API를 제공하는 라이브러리는 C# 관행에 따라 XML 주석을 통해 문서화할 수 있습니다. 예를 들어 Doxygen 형식으로 코멘트를 C++ 로 전송하는 것은 간단한 작업이 아닙니다. 마크업 외에도 유형에 대한 참조(C#에서는 전체 이름이 점으로, C++에서는 콜론 한 쌍으로 작성되므로), 해당 멤버를 대체해야 하며, 속성을 사용하는 경우 게터인지 세터인지도 이해해야 합니다. 또한 의미가 없고 불완전할 수 있는 코드 조각을 번역합니다.
이 작업은 번역기 자체와 외부 유틸리티(예: 생성된 XML 문서를 분석하고 메서드 사용 예제와 같은 조각을 추가로 준비하는 등)를 통해 해결됩니다.
보시다시피 코드 변환을 위한 전문 프레임워크는 C# 코드를 C++로 고품질 번역하는 것 외에도 소스 코드의 번역 가능성을 결정하고, 필요한 경우 언어 버전을 낮추고, 변환된 라이브러리 사용 예제와 해당 설명서를 번역할 수 있어야 합니다.