Pull to refresh

Хостинг CLR в неуправляемом приложении

.NET Framework предоставляет большое количество способов взаимодействия управляемого и неуправляемого кода, включая COM Interop и P/Invoke. Существует много материалов, посвящённых данному вопросу. Однако о такой возможности, как запуск CRL в неуправляемом процессе посредством CLR Hosting API, написано сравнительно немного. Запуск среды выполнения в неуправляемом приложении может быть полезен, в следующих случаях:

  • поддержка расширений, написанных на управляемых языках;
  • создание навесных защит для управляемых приложений;
  • управление работой CLR;
  • сложные случаи отладки;
  • постепенный перевод большого неуправляемого приложения на .NET.

Например, хостинг CLR используется в приложениях Microsoft Office (управляемые надстройки) и Microsoft SQL Server (CLR Stored Procedures).

Развитие CLR Hosting API


.NET Framework 1.x

В первой версия CLR Hosting API для взаимодействия со средой выполнения используется интерфейс ICorRuntimeHost, который можно получить при помощи статических функций CorBindTo* (например, CorBindToRuntie) библиотеки MSCorEE.dll.
.NET Framework 2.0

В этой версии многие аспекты хостинга CLR перенесены из неуправляемого в управляемый код (программист может управлять хостингом при помощи наследника класса AppDomainManager). Появился новый интерфейс ICLRRuntimeHost.
.NET Framework 4.0 и In-Process Side-by-Side

Предыдущие версии CLR Hosting API имели важное ограничение – было невозможно запустить более одной версии CLR в одном процессе. Это означает, что если есть две надстройки, написанные с использованием разных версий CLR, то, как минимум, одну из них придется запускать не под той версией исполняющей среды, для которой она разрабатывалась. Начиная с .NET Framework 4.0 появилась возможность загрузить нескольких версий CLR в одном процессе, при этом одновременно смогут работать сколько угодно версий исполняющей среды (начиная c 4.0) и одна из старых версий (CLR1.1 или CLR2.0). Старые статические функции (CorBindTo*) объявлены устаревшими, вместо них предлагается использовать функцию CLRCreateInstance и методы интерфейсов ICLRMetaHost и ICLRRuntimeInfo.

Управление работой CLR


В CLR Hosting API можно выделить две большие группы интерфейсов:
  • интерфейсы хост-диспетчеров (host managers), их имена начинаются с префикса IHost, они реализуются на стороне неуправляемого приложения и вызываются CLR;
  • интерфейсы диспетчеров CLR (CLR managers), которые реализуются CLR и вызываются на стороне неуправляемого приложения.

При помощи этих интерфейсов можно контролировать такие аспекты работы CLR, как:
  • работа с памятью (ICLRGCManager, ICLRMemoryNotificationCallback, IHostGCManager, IHostMAlloc, IHostMemoryManager);
  • работа с потоками(ICLRTaskManager, IHostTaskManager, IHostThreadPoolManger);
  • синхронизация потоков(ICLRSyncManager, IHostCrst, IHostSyncManager, IHostManualEvent);
  • загрузка сборок (ICLRAssemblyIdentityManager, IHostAssemblyStore, IHostAssemblyManager);
  • настройка CLR (ICLRControl, ICLRPolicyManager, ICLRDebugManager).


Пример использования CLR Hosting API


#include <metahost.h>
#pragma comment(lib, "mscoree.lib")

int wmain( int argc, wchar_t** argv )
{
ICLRMetaHost *pMetaHost = nullptr;
ICLRRuntimeInfo *pCLRRuntimeInfo = nullptr;
ICLRRuntimeHost *pCLRRuntimeHost = nullptr;
__try
{
HRESULT hr;
// Получаем среду выполнения
hr = CLRCreateInstance( CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost );
if ( FAILED(hr) ) return -1;

hr = pMetaHost->GetRuntime( L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&pCLRRuntimeInfo );

BOOL bCLRIsLoadable;
hr = pCLRRuntimeInfo->IsLoadable( &bCLRIsLoadable );
if ( FAILED( hr ) ) return -1;
if ( ! bCLRIsLoadable ) return -1;

hr = pCLRRuntimeInfo->GetInterface( CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pCLRRuntimeHost );
if ( FAILED(hr) ) return -1;

// Запускаем CLR
hr = pCLRRuntimeHost->Start();
if ( FAILED(hr) ) return -1;

// Загружаем сборку и вызываем в ней метод
DWORD nRet;
hr = pCLRRuntimeHost->ExecuteInDefaultAppDomain( L"TestLib.dll", L"TestLib.Foo", L"Bar", L"", &nRet );
if ( FAILED(hr) ) return -1;
}
__finally
{
// Освобождаем ресурсы
if ( pCLRRuntimeHost ) { pCLRRuntimeHost->Release(); pCLRRuntimeHost = nullptr; }
if ( pCLRRuntimeInfo ) { pCLRRuntimeInfo->Release(); pCLRRuntimeInfo = nullptr; }
if ( pMetaHost ) { pMetaHost->Release(); pMetaHost = nullptr; }
}
return 0;
}


Литература



Для всех источников, кроме первого, есть переводы на русский язык.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.