C cli что это
Перейти к содержимому

C cli что это

  • автор:

Программирование .NET с использованием C++/CLI

По умолчанию проекты CLR, созданные с помощью Visual Studio 2015, предназначены для целевой платформы .NET Framework 4.5.2. При создании нового проекта можно использовать платформа .NET Framework 4.6. В диалоговом окне «Новый проект» измените целевую платформу в раскрывающемся списке в верхней части диалогового окна. Чтобы изменить целевую платформу для существующего проекта, закройте проект, измените файл проекта ( .vcxproj ) и измените значение целевой платформы на 4.6. Изменения вступают в силу при следующем открытии проекта.

В Visual Studio 2017 целевая платформа .NET Framework по умолчанию — 4.6.1. Селектор версий Платформы находится в нижней части диалогового окна «Новый проект «.

Установка поддержки C++/CLI в Visual Studio 2017

При установке рабочей нагрузки Visual Studio C++/CLI сама по умолчанию не устанавливается. Чтобы установить компонент после установки Visual Studio, откройте установщик Visual Studio, выбрав меню «Пуск Windows» и найдите установщик Visual Studio. Нажмите кнопку «Изменить» рядом с установленной версией Visual Studio. Перейдите на вкладку «Отдельные компоненты». Прокрутите вниз до раздела «Компиляторы», средства сборки и среды выполнения и выберите поддержку C++/CLI. Выберите «Изменить», чтобы скачать необходимые файлы и обновить Visual Studio.

В Visual Studio 2019 целевая платформа по умолчанию для проектов .NET Core — 5.0. Для проектов платформа .NET Framework по умолчанию используется значение 4.7.2. Селектор версий платформа .NET Framework находится на странице «Настройка нового проекта» диалогового окна «Создание нового проекта«.

Установка поддержки C++/CLI в Visual Studio 2019

При установке рабочей нагрузки Visual Studio C++/CLI сама по умолчанию не устанавливается. Чтобы установить компонент после установки Visual Studio, откройте установщик Visual Studio, выбрав меню «Пуск Windows» и найдите установщик Visual Studio. Нажмите кнопку «Изменить» рядом с установленной версией Visual Studio. Перейдите на вкладку «Отдельные компоненты». Прокрутите вниз до раздела «Компиляторы», средства сборки и среды выполнения и выберите поддержку C++/CLI для средств сборки версии 142 (последняя версия). Выберите «Изменить», чтобы скачать необходимые файлы и обновить Visual Studio.

В Visual Studio 2022 целевая платформа по умолчанию для проектов .NET Core — 6.0. Для проектов платформа .NET Framework по умолчанию используется значение 4.7.2. Селектор версий платформа .NET Framework находится на странице «Настройка нового проекта» диалогового окна «Создание нового проекта«.

Установка поддержки C++/CLI в Visual Studio 2022

При установке рабочей нагрузки Visual Studio C++/CLI сама по умолчанию не устанавливается. Чтобы установить компонент после установки Visual Studio, откройте установщик Visual Studio, выбрав меню «Пуск Windows» и найдите установщик Visual Studio. Нажмите кнопку «Изменить» рядом с установленной версией Visual Studio. Перейдите на вкладку «Отдельные компоненты». Прокрутите вниз до раздела «Компиляторы», средства сборки и среды выполнения и выберите поддержку C++/CLI для средств сборки версии 143 (последняя версия). Выберите «Изменить», чтобы скачать необходимые файлы и обновить Visual Studio.

Расширения языка C++/CLI

— это набор расширений языка C++, позволяющий создавать гибридные управляемые и низкоуровневые библиотеки DLL. С применением расширений C++/CLI вы сможете определять управляемые и неуправляемые классы и функции в пределах одного файла .cpp, использовать управляемые и низкоуровневые типы C и C++, как в обычном программном коде на C++, то есть простым подключением заголовочного файла и связыванием с библиотекой. Эти широчайшие возможности можно использовать для создания управляемых типов-оберток, пригодных для использования в любом языке .NET, а так же низкоуровневые классы-обертки и функции (доступные через файлы .dll, .lib и .h), пригодные для использования в программном коде на C/C++.

При использовании расширения C++/CLI маршалинг выполняется вручную, благодаря чему разработчик имеет более полный контроль и более полное представление о накладных расходах. Расширение C++/CLI с успехом можно использовать там, где механизм P/Invoke оказывается бесполезен, например, для маршалинга структур переменной длины. Еще одно преимущество расширения C++/CLI состоит в том, что оно позволяет имитировать интерфейс объединения запросов, даже если у вас нет доступа к исходным текстам вызывающего кода, многократно вызывая низкоуровневые методы без необходимости каждый раз пересекать границу между управляемым и неуправляемым кодом.

В коде, представленном ниже, мы реализовали неуправляемый класс NativeEmployee и управляемый класс Employee, служащий оберткой для первого. Управляемый код будет обращаться только к управляемому классу.

#include #include #include #include using namespace System; using namespace System::Runtime::InteropServices; class NativeEmployee < public: NativeEmployee(const wchar_t *employeeName, int age) : _employeeName(employeeName), _employeeAge(age) < >void DoWork(const wchar_t **tasks, int numTasks) < for (int i = 0; i < numTasks; i++) < wprintf(L"Пользователь %s работает в задаче %s\n", _employeeName.c_str(), tasks[i]); >> int GetAge() const < return _employeeAge; >const wchar_t *GetName() const < return _employeeName.c_str(); >private: std::wstring _employeeName; int _employeeAge; >; #pragma managed namespace EmployeeLib < public ref class Employee < < public: Employee(String ^employeeName, int age) < // Вариант 1: // IntPtr pEmployeeName = Marshal::StringToHGlobalUni(employeeName); // m_pEmployee = new NativeEmployee( // reinterpret_cast(pEmployeeName.ToPointer()), age); // Marshal::FreeHGlobal(pEmployeeName); // Вариант 2 (прямой указатель на закрепленную // управляемую строку, самый быстрый): pin_ptr ppEmployeeName = PtrToStringChars(employeeName); _employee = new NativeEmployee(ppEmployeeName, age); > ~Employee() < delete _employee; _employee = nullptr; >int GetAge() < return _employee->GetAge(); > String ^GetName() < // Вариант 1: // return Marshal::PtrToStringUni( // (IntPtr)(void *) _employee->GetName()); // Вариант 2: return msclr::interop::marshal_as(_employee->GetName()); // Вариант 3 (самый быстрый): return gcnew String(_employee->GetName()); > void DoWork(array^ tasks) < // marshal_context - это управляемый класс, размещаемый // (в динамической памяти сборщика мусора) с использованием // семантики, напоминающей стек. Его деструктор IDisposable::Dispose() // будет вызван после выхода из области видимости этой функции msclr::interop::marshal_context ctx; const wchar_t **pTasks = new const wchar_t*[tasks->Length]; for (int i = 0; i < tasks->Length; i++) < String ^t = tasks[i]; pTasks[i] = ctx.marshal_as(t); > m_pEmployee->DoWork(pTasks, tasks->Length); // деструктор контекста освободит неуправляемую // память, выделенную методом marshal_as delete[] pTasks; > private: NativeEmployee *_employee; >; >

Взглянув на код, можно увидеть, что конструктор Employee демонстрирует два способа преобразования управляемых строк в неуправляемый: первый основан на выделении памяти с помощью GlobalAlloc, которую необходимо будет освободить явно, а второй временно закрепляет управляемую строку в памяти и возвращает прямой указатель. Второй способ выполняется быстрее, но его можно использовать, только когда неуправляемый код принимает строки, завершающиеся нулевым символом, в кодировке UTF-16, и он не записывает ничего в память по указателю. Кроме того, закрепление управляемых объектов на длительное время может привести к фрагментации памяти, поэтому, если перечисленные требования не удовлетворяются, вам придется прибегнуть к копированию строк.

Метод GetName() класса Employee демонстрирует три способа преобразования неуправляемых строк в управляемые: первый основан на использовании класса System.Runtime.InteropServices.Marshal, второй использует функцию marshal_as, объявленную в заголовочном файле msclr/marshal.h, и, наконец, третий использует конструктор класса System.String, являющийся наиболее быстрым.

Метод DoWork() класса Employee принимает управляемый массив (или управляемые строки) и преобразует его в массив указателей типа wchar_t, указывающих на строки; фактически это массив строк в стиле языка C. Преобразование управляемых строк в неуправляемые выполняется с применением метода marshal_as класса объекта marshal_context. В отличие от глобальной функции marshal_as, объект marshal_context используется для преобразований, требующих освобождения занимаемых при этом ресурсов. Обычно для преобразования управляемых данных в неуправляемые метод marshal_as выделяет неуправляемую память, которую следует освободить после выполнения операции. Объект marshal_context содержит связанный список операций освобождения ресурсов, которые выполняются в момент уничтожения объекта.

Подводя итоги можно сказать, что расширение C++/CLI обеспечивает полный контроль над маршалингом и не требует дублирования объявлений функций, что чревато ошибками, особенно когда часто приходится изменять сигнатуры неуправляемых функций.

Вспомогательная библиотека marshal_as

В этом разделе мы остановимся на вспомогательной библиотеке marshal_as, входящей в состав версии Visual C++ 2008 и выше. marshal_as — это библиотека шаблонов, упрощающая реализацию маршалиига управляемых типов в неуправляемые и обратно. Она способна преобразовывать многие неуправляемые строковые типы, такие как char*, wchar_t*, std::string, std::wstring, CStringT, CStringT, BSTR, bstr_t и CComBSTR, в управляемые типы и обратно. Она способна автоматически выполнять преобразование символов Юникода и ANSI, а также выделять и освобождать память.

Библиотека объявлена и реализована в файлах marshal.h (базовые типы), marshal_windows.h (типы Windows), marshal_cppstd.h (типы данных STL) и marshal_atl.h (типы данных ATL).

Имеется возможность расширять библиотеку marshal_as реализацией преобразований пользовательских типов. Это помогает избежать дублирования кода, когда требуется организовать маршалинг одного и того же типа во многих местах в программе, и дает возможность обеспечить единообразие синтаксиса маршалинга разных типов.

В следующем фрагменте демонстрируется пример расширения библиотеки marshal_as поддержкой преобразования управляемого массива строк в эквивалентный неуправляемый массив строк:

namespace msclr < namespace interop < template<>ref class context_node^> : public context_node_base < private: const wchar_t** _tasks; marshal_context _context; public: context_node(const wchar_t**& toObject, array^ fromObject) < // здесь начинается логика преобразования _tasks = NULL; const wchar_t **pTasks = new const wchar_t*[fromObject->Length]; for (int i = 0; i < fromObject->Length; i++) < String ^t = fromObject[i]; pTasks[i] = _context.marshal_as(t); > toObject = _tasks = pTasks; > ~context_node() < this->!context_node(); > protected: !context_node() < // При удалении контекста будет освобождена память, // выделенная для строк (и принадлежащая marshal_context), // поэтому массив - единственная память, // которую требуется освободить if (_tasks != nullptr) < delete[] _tasks; _tasks = nullptr; >> >; > > // Теперь можно переписать метод Employee::DoWork: void DoWork(array^ tasks) < // Вся неуправляемая память освобождается автоматически, // как только marshal_context выйдет из области видимости msclr::interop::marshal_context ctx; _employee->DoWork(ctx.marshal_as(tasks), tasks->Length); >

Код на языке IL и неуправляемый код

Неуправляемый класс по умолчанию будет скомпилирован расширением C++/CLI в код на языке IL, а не в машинный код. Это может ухудшать производительность в сравнении с оптимизированным машинным кодом, потому что компилятор Visual C++ способен оптимизировать код лучше, чем JIT-компилятор.

Чтобы повлиять на процедуру компиляции можно, добавив объявление #pragma unmanaged или #pragma managed перед требуемым разделом кода. Кроме того, в проектах VC++ имеется возможность включать поддержку C++/CLI для отдельных единиц компиляции (файлов .cpp).

Эффективные приемы взаимодействий

Итак, в этой и предыдущих статьях вы познакомились с небезопасным кодом, особенностями реализации различных механизмов взаимодействий, влиянием на производительность каждой из особенностей и узнали, как можно ослабить это влияние. Вашему вниманию были представлены наиболее эффективные приемы увеличения производительности операций взаимодействий и упрощения их реализации (например, с помощью библиотеки marshal_as и генератора сигнатур для P/Invoke). Давайте подытожим все приведенные ранее советы, относительно небезопасного кода.

Ниже перечислены наиболее эффективные приемы реализации взаимодействий:

  • проектируя интерфейсы, старайтесь сводить к минимуму количество переходов через границу между управляемым и неуправляемым кодом, например, объединяя задания;
  • уменьшайте количество взаимодействий, совмещая несколько вызовов простых функций в одном вызове;
  • реализуйте интерфейс IDisposable, если неуправляемые ресурсы сохраняются между вызовами;
  • используйте пулы памяти и выделяйте блоки неуправляемой памяти;
  • используйте небезопасный код для интерпретации данных (например, в сетевых протоколах);
  • явно именуйте вызываемые функции и используйте ExactSpelling=true;
  • используйте параметры двоично совместимых типов, где это возможно;
  • избегайте преобразования Юникода в ANSI, когда это возможно;
  • вручную преобразуйте строки в/из IntPtr;
  • используйте расширение C++/CLI, обеспечивающее лучшие управляемость и производительность при взаимодействиях с кодом на C/C++ и COM-объектами;
  • указывайте атрибуты [In] и [Out], чтобы избежать ненужного маршалинга;
  • избегайте закрепления долгоживущих объектов;
  • используйте метод ReleaseComObject при необходимости;
  • используйте атрибут SuppressUnmanagedCodeSecurityAttribute в окружениях, заслуживающих доверия;
  • используйте утилиту tlbimp.exe с ключом /unsafe в окружениях, заслуживающих доверия;
  • избегайте или старайтесь уменьшать количество вызовов через границы подразделений COM;
  • при возможности используйте атрибут AspCompat в приложениях ASP.NET, чтобы уменьшить количество вызовов через границы подразделений COM.

Пошаговое руководство. Компиляция программы C++/CLI, предназначенной для среды CLR в Visual Studio

С помощью C++/CLI можно создавать программы C++, использующие классы .NET, а также собственные типы C++. C++/CLI предназначен для использования в консольных приложениях и в библиотеках DLL, которые упаковывают собственный код C++ и делают его доступными из программ .NET. Чтобы создать пользовательский интерфейс Windows на основе .NET, используйте C# или Visual Basic.

Для этой процедуры можно ввести собственную программу C++ или использовать одну из примеров программ. Пример программы, используемый в этой процедуре, создает текстовый файл textfile.txt и сохраняет его в каталог проекта.

Необходимые компоненты

  • Для работы необходимо владеть основами языка C++.
  • В Visual Studio 2017 и более поздних версиях поддержка C++/CLI является необязательным компонентом. Чтобы установить его, откройте установщик Visual Studio из Windows меню . Убедитесь, что плитка «Разработка компьютеров с помощью C++ проверка» и в разделе «Необязательные компоненты» также проверка поддержка C++/CLI.

Создание нового проекта

Приведенные ниже инструкции немного отличаются в зависимости от используемой версии Visual Studio. Чтобы ознакомиться с документацией по предпочтительной версии Visual Studio, используйте селектор Версия. Он находится в верхней части оглавления на этой странице.

Создание проекта C++/CLI в Visual Studio

  1. В Обозреватель решений щелкните правой кнопкой мыши вверху, чтобы открыть диалоговое окно «Создать проект«.
  2. В верхней части диалогового окна введите CLR в поле поиска и выберите clR Empty Project (платформа .NET Framework) из списка результатов.
  3. Нажмите кнопку Создать, чтобы создать проект.

Создание проекта C++/CLI в Visual Studio 2017

  1. Создание проекта В меню Файл укажите Создать, затем нажмите Проект.
  2. В списке типов проектов Visual C++ щелкните CLR, а затем — Пустой проект CLR.
  3. Введите имя проекта. По умолчанию содержащее проект решение имеет то же имя, что и новый проект, но можно ввести другое имя. При необходимости можно ввести другое расположение для проекта.
  4. Нажмите кнопку ОК для создания проекта.

Создание проекта C++/CLI в Visual Studio 2015

  1. Создание проекта В меню Файл укажите Создать, затем нажмите Проект.
  2. В списке типов проектов Visual C++ щелкните CLR, а затем — Пустой проект CLR.
  3. Введите имя проекта. По умолчанию содержащее проект решение имеет то же имя, что и новый проект, но можно ввести другое имя. При необходимости можно ввести другое расположение для проекта.
  4. Нажмите кнопку ОК для создания проекта.

Добавление исходного файла

  1. Если обозреватель решений не отображается, в меню Вид выберите пунукт Обозреватель решений.
  2. Добавьте новый исходный файл в проект:
    • Щелкните правой кнопкой мыши папку Исходные файлы в обозревателе решений, наведите указатель мыши на пункт Добавить и щелкните Новый элемент.
    • Щелкните элемент Файл C++ (.cpp), введите имя файла и нажмите кнопу Добавить.

Файл с расширением .cpp отображается в папке Исходные файлы в обозревателе решений, а окно с вкладками отображается в месте ввода кода в этом файле.

Примечание. При выборе пустого шаблона проекта CLR автоматически задается параметр компилятора /clr . Чтобы проверить это, щелкните правой кнопкой мыши проект в обозревателе решений и выберите Свойства, а затем установите флажок Поддержка общеязыковой среды выполнения (CLR) в узле Общие окна Свойства конфигурации.

Что такое CLI (c++/CLI)?

Читал, это как то связано с .net. А что это вообще такое, как работает и зачем нужно? И как это отключить (слышал есть такое) в visual studio 2010?

Отслеживать
23.8k 3 3 золотых знака 47 47 серебряных знаков 61 61 бронзовый знак
задан 9 ноя 2012 в 19:11
1,267 2 2 золотых знака 21 21 серебряный знак 56 56 бронзовых знаков
9 ноя 2012 в 19:23
@Котик_хочет_кушать по-буржуйски я не гу-гу
9 ноя 2012 в 19:25
Вообще-то в левой части страницы и на русский ссылка есть: ru.wikipedia.org/wiki/C%2B%2B/CLI
9 ноя 2012 в 19:47

@TAPAHbl4, уважение у вас прямо таки «зашкаливает» =D. Если не уверены, пишите хотя бы в комментариях.

9 ноя 2012 в 20:36

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

CLI в данном случае не командная строка, а Common Language Infrastructure, то есть, говоря языком Пушкина и Достоевского, Общеязыковая Инфраструктура. CLI не что иное, как спецификация, в которой описывается архитектура .NET и связанных с ним проектов (в частности, Mono) C++/CLI не что иное, как управляемый С++, код которого транслируется в CIL ( не путать с CLI), представляющий собой что-то вроде ассемблера для .net

Отслеживать
ответ дан 9 ноя 2012 в 21:44
DreamChild DreamChild
36.2k 3 3 золотых знака 45 45 серебряных знаков 85 85 бронзовых знаков

    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.26.3951

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *