C++/CLI¶
C++/CLI (Common Language Infrastructure) — это язык программирования и набор расширений для языка C++, разработанный компанией Microsoft. Он предназначен для создания программных компонентов, работающих под управлением платформы .NET Framework (и её кроссплатформенной реализации .NET Core/.NET 5+). C++/CLI представляет собой диалект C++, который добавляет синтаксические конструкции для работы с управляемым кодом (managed code), выполняемым в среде Common Language Runtime (CLR), и позволяет напрямую взаимодействовать с неуправляемым (native) кодом. Стандарт языка был утверждён рабочей группой Ecma International в 2005 году (ECMA-372).
¶История
C++/CLI был создан как преемник более ранней технологии Managed Extensions for C++ (MC++), которая впервые появилась в Visual Studio .NET 2002. Managed Extensions for C++ страдали от громоздкого синтаксиса и неудобств при смешивании управляемого и неуправляемого кода. Например, для объявления управляемого класса требовалось использовать ключевое слово __gc, а для указателя на управляемый объект — __gc *. Это делало код трудночитаемым и затрудняло его поддержку.
В 2005 году Microsoft представила C++/CLI как часть Visual Studio 2005. Новый язык ввёл более лаконичный и интуитивно понятный синтаксис, основанный на использовании шляпок (^) для обозначения дескрипторов (handles) управляемых объектов и ключевого слова ref для объявления ссылочных типов. Стандарт ECMA-372 был опубликован в декабре 2005 года. Несмотря на то, что C++/CLI не получил широкого распространения за пределами экосистемы Microsoft, он остаётся важным инструментом для интеграции устаревшего (legacy) C++ кода с платформой .NET.
¶Ключевые особенности
C++/CLI принципиально отличается от стандартного C++ (ISO C++) тем, что позволяет в рамках одного модуля (сборки) сочетать управляемый и неуправляемый код. Это достигается за счёт следующих механизмов:
¶Управляемые типы
В C++/CLI введены два новых семейства классов:
- Ссылочные классы (reference classes) — объявляются с ключевым словом
ref class. Экземпляры таких классов размещаются в управляемой куче (managed heap) и собираются сборщиком мусора (garbage collector). Доступ к ним осуществляется через дескрипторы (^), а не через обычные указатели (*). Пример:
``cpp ref class MyClass { public: void DoSomething() { } }; // Использование: MyClass^ obj = gcnew MyClass(); ``
- Значимые классы (value classes) — объявляются с ключевым словом
value class. Это структуры, которые хранятся непосредственно в стеке или в составе других объектов. Они не могут иметь виртуальных методов и не наследуются (кроме как отSystem::ValueType). Пример:
``cpp value class Point { public: int X; int Y; }; ``
¶Дескрипторы и трекинговые ссылки
- Дескриптор (handle) — обозначается символом
^. Это аналог указателя, но для управляемых объектов. Дескриптор может бытьnullptr(в C++/CLI для этой цели используется ключевое словоnullptr, а неNULLили0). Сборщик мусора может перемещать объекты в памяти, но дескриптор остаётся действительным, так как CLR автоматически обновляет его значение. - Трекинговая ссылка (tracking reference) — обозначается
%. Это аналог ссылки в C++ (&), но для управляемых объектов. Позволяет передавать управляемые объекты по ссылке без копирования.
¶Сборка мусора
В C++/CLI управляемые объекты не требуют явного освобождения памяти — этим занимается сборщик мусора CLR. Однако при работе с неуправляемыми ресурсами (файлы, сокеты, дескрипторы Windows) необходимо реализовать шаблон IDisposable (через деструктор, который в C++/CLI автоматически генерирует метод Dispose()). Деструктор управляемого класса в C++/CLI вызывается детерминированно при выходе из области видимости или при явном вызове delete, что отличает его от финализатора.
¶Взаимодействие с неуправляемым кодом
C++/CLI обеспечивает наиболее тесную интеграцию между управляемым и неуправляемым кодом среди всех языков .NET. Это достигается за счёт:
- Прямого вызова неуправляемых функций — можно использовать обычные заголовочные файлы C++ и библиотеки (DLL) без обёрток P/Invoke.
- Смешивания типов — в одном файле
.cppможно объявлять как управляемые (ref class), так и неуправляемые (class) классы. - Маршалинга (marshaling) — автоматического преобразования типов между управляемой и неуправляемой средами. Для сложных случаев доступен класс
System::Runtime::InteropServices::Marshal.
¶Синтаксические отличия от стандартного C++
C++/CLI вводит ряд ключевых слов и модификаторов, отсутствующих в ISO C++:
| Конструкция | Назначение |
|---|---|
ref class / ref struct | Объявление ссылочного типа (управляемого) |
value class / value struct | Объявление значимого типа |
interface class | Объявление интерфейса (аналог interface в C#) |
gcnew | Оператор создания управляемого объекта (вместо new) |
^ (шляпка) | Дескриптор управляемого объекта |
% (процент) | Трекинговая ссылка |
nullptr | Нулевой дескриптор (в C++/CLI — ключевое слово) |
generic | Параметризованные типы (аналог шаблонов, но для CLR) |
property | Свойства (get/set) |
event | События (аналог делегатов в C#) |
¶Применение
C++/CLI используется в нескольких ключевых областях:
¶Создание обёрток (wrappers) для неуправляемых библиотек
Основное применение C++/CLI — создание промежуточных сборок (так называемых «mixed assemblies»), которые позволяют вызывать неуправляемый C++ код из управляемых языков (C#, Visual Basic .NET, F#). Это особенно актуально для:
- Переноса устаревших библиотек (legacy code) на платформу .NET без полного переписывания.
- Интеграции высокопроизводительных вычислительных модулей (например, OpenCV, Boost, DirectX) с .NET-приложениями.
- Обеспечения доступа к низкоуровневым API Windows (Win32 API) через более удобный интерфейс.
¶Разработка компонентов для .NET
C++/CLI позволяет создавать сборки, которые могут быть использованы в любом .NET-языке. При этом разработчик имеет полный контроль над управлением памятью и производительностью, что недоступно в C# или VB.NET.
¶Системное программирование
В некоторых случаях C++/CLI применяется для написания драйверов, системных утилит и компонентов, требующих прямого доступа к аппаратуре, но при этом желающих использовать преимущества .NET (например, управление потоками, безопасность типов).
¶Критика и ограничения
C++/CLI подвергается критике по нескольким причинам:
- Сложность синтаксиса — смешение двух парадигм (управляемой и неуправляемой) в одном языке приводит к запутанному коду. Наличие двух видов указателей (
*и^), двух видов ссылок (&и%), а также двух систем управления памятью (сборщик мусора и ручноеnew/delete) требует высокой квалификации от программиста. - Ограниченная поддержка — C++/CLI не поддерживается в кроссплатформенных реализациях .NET (например, Mono, .NET Core до версии 5) в полном объёме. Начиная с .NET 5, Microsoft рекомендует использовать C++/CLI только для Windows-приложений, а для кроссплатформенной разработки — переходить на стандартный C++ с P/Invoke или на C# с использованием
System.Runtime.InteropServices. - Производительность — хотя C++/CLI позволяет писать высокопроизводительный код, накладные расходы на переход между управляемым и неуправляемым контекстами (трансляция вызовов, маршалинг) могут быть значительными.
- Отсутствие эволюции — после выхода стандарта ECMA-372 в 2005 году язык практически не развивался. Новые возможности C++ (C++11, C++14, C++17, C++20) не были перенесены в C++/CLI. В Visual Studio 2019 и 2022 поддержка C++/CLI сохраняется, но без существенных изменений.
¶Пример кода
Простой пример, демонстрирующий смешение управляемого и неуправляемого кода:
```cpp // Неуправляемый класс class NativeClass { public: int Add(int a, int b) { return a + b; } };
// Управляемая обёртка public ref class ManagedWrapper { private: NativeClass* native; // Указатель на неуправляемый объект public: ManagedWrapper() { native = new NativeClass(); } ~ManagedWrapper() { delete native; // Освобождение неуправляемой памяти } int Add(int a, int b) { return native->Add(a, b); } }; ```
Этот код может быть скомпилирован в сборку .dll и использован в C#:
``csharp var wrapper = new ManagedWrapper(); int result = wrapper.Add(3, 4); // result = 7 ``
¶Статус и будущее
На 2025 год C++/CLI остаётся поддерживаемым языком в Visual Studio, но его использование ограничено экосистемой Windows. Microsoft рекомендует для новых проектов по возможности использовать стандартный C++ с P/Invoke или C# с System.Runtime.InteropServices. Однако для интеграции крупных неуправляемых библиотек (например, графических движков, библиотек компьютерного зрения) C++/CLI остаётся наиболее эффективным инструментом.
В .NET 5+ была добавлена поддержка сборок C++/CLI только для Windows (через конфигурацию RuntimeIdentifier). Кроссплатформенная разработка с C++/CLI невозможна.
¶Источники
- ECMA-372: C++/CLI Language Specification (2005)
- Microsoft Docs: C++/CLI for .NET Framework
- Herb Sutter, «C++/CLI: A New Language for the CLR» (2005)
- MSDN Magazine: «C++/CLI: A Powerful Bridge Between Managed and Native Code» (2006)
- Visual Studio 2022 Documentation: Mixed (Native and Managed) Assemblies
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →


