Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Podobnie jak cały kod zarządzany, aplikacje platformy .NET są wykonywane przez hosta. Host jest odpowiedzialny za uruchamianie środowiska uruchomieniowego (w tym składników, takich jak JIT i moduł odśmiecania pamięci) oraz wywoływanie zarządzanych punktów wejścia.
Hostowanie środowiska uruchomieniowego platformy .NET jest zaawansowanym scenariuszem, a w większości przypadków deweloperzy platformy .NET nie muszą martwić się o hosting, ponieważ procesy kompilacji platformy .NET zapewniają domyślny host do uruchamiania aplikacji platformy .NET. Jednak w pewnych wyspecjalizowanych okolicznościach może być przydatne jawne hostowanie środowiska uruchomieniowego platformy .NET— jako środka wywoływania kodu zarządzanego w procesie natywnym lub w celu uzyskania większej kontroli nad działaniem środowiska uruchomieniowego.
Ten artykuł zawiera omówienie kroków niezbędnych do uruchomienia środowiska uruchomieniowego platformy .NET z kodu natywnego i wykonania w nim kodu zarządzanego.
Wymagania wstępne
Ponieważ hosty są aplikacjami natywnymi, w tym samouczku opisano tworzenie aplikacji języka C++ do hostowania platformy .NET. Będzie potrzebne środowisko programistyczne języka C++ (takie jak udostępnione przez program Visual Studio).
Aby przetestować hosta, należy skompilować składnik platformy .NET, więc należy zainstalować .NET SDK. Zawiera niezbędne nagłówki i biblioteki do połączenia z programem. Na przykład w systemie Windows z zestawem .NET 8 SDK pliki można znaleźć w pliku C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Host.win-x64\8.0.4\runtimes\win-x64\native
.
Hostowanie interfejsów API
Hostowanie środowiska uruchomieniowego platformy .NET w wersji .NET Core 3.0 i nowszych odbywa się przy użyciu interfejsów API bibliotek nethost
i hostfxr
. Te punkty wejścia obsługują złożoność znajdowania i konfigurowania środowiska uruchomieniowego na potrzeby inicjowania oraz umożliwiają uruchamianie aplikacji zarządzanej i wywoływanie statycznej metody zarządzanej.
Przed platformą .NET Core 3.0 jedyną opcją hostowania środowiska uruchomieniowego było użycie interfejsu coreclrhost.h
API. Ten interfejs API hostingu jest teraz przestarzały i nie powinien być używany do hostowania środowisk uruchomieniowych platformy .NET Core 3.0 i wyższych.
Utwórz hosta przy użyciu nethost.h
i hostfxr.h
Przykładowy host, który demonstruje kroki opisane w samouczku poniżej, jest dostępny w repozytorium GitHub dotnet/samples. Komentarze w przykładzie wyraźnie przypisują ponumerowane kroki z tego samouczka do miejsc, gdzie są wykonywane w przykładzie. Aby uzyskać instrukcje dotyczące pobierania, zobacz Przykłady i samouczki.
Należy pamiętać, że przykładowy host ma być używany do celów szkoleniowych, dlatego jest mało rygorystyczny w sprawdzaniu błędów i jest zaprojektowany, aby podkreślić czytelność przed wydajnością.
Poniższe kroki szczegółowo opisują, jak używać bibliotek nethost
i hostfxr
do uruchomienia środowiska uruchomieniowego platformy .NET w aplikacji natywnej oraz do wywołania zarządzanej metody statycznej. W przykładzie użyto nagłówków i biblioteki nethost
, a także nagłówków coreclr_delegates.h
i hostfxr.h
zainstalowanych wraz z zestawem .NET SDK.
Krok 1. Ładowanie hostfxr
i pobieranie wyeksportowanych funkcji hostingu
Biblioteka nethost
udostępnia get_hostfxr_path
funkcję lokalizowania hostfxr
biblioteki. Biblioteka hostfxr
uwidacznia funkcje hostowania środowiska uruchomieniowego platformy .NET. Pełną listę funkcji można znaleźć w hostfxr.h
dokumencie projektowania natywnego hostingu. W przykładzie i w tym samouczku są używane następujące elementy:
-
hostfxr_initialize_for_runtime_config
: inicjuje kontekst hosta i przygotowuje do uruchomienia środowiska uruchomieniowego platformy .NET przy użyciu określonej konfiguracji środowiska uruchomieniowego. -
hostfxr_get_runtime_delegate
: Pobiera delegata do funkcjonalności środowiska uruchomieniowego. -
hostfxr_close
: zamyka kontekst hosta.
Biblioteka hostfxr
jest odnajdywana za pomocą interfejsu get_hostfxr_path
API z biblioteki nethost
. Następnie jest ładowany, a jego eksporty są pobierane.
// Using the nethost library, discover the location of hostfxr and get exports
bool load_hostfxr()
{
// Pre-allocate a large buffer for the path to hostfxr
char_t buffer[MAX_PATH];
size_t buffer_size = sizeof(buffer) / sizeof(char_t);
int rc = get_hostfxr_path(buffer, &buffer_size, nullptr);
if (rc != 0)
return false;
// Load hostfxr and get desired exports
void *lib = load_library(buffer);
init_fptr = (hostfxr_initialize_for_runtime_config_fn)get_export(lib, "hostfxr_initialize_for_runtime_config");
get_delegate_fptr = (hostfxr_get_runtime_delegate_fn)get_export(lib, "hostfxr_get_runtime_delegate");
close_fptr = (hostfxr_close_fn)get_export(lib, "hostfxr_close");
return (init_fptr && get_delegate_fptr && close_fptr);
}
W przykładzie użyto następujących elementów:
#include <nethost.h>
#include <coreclr_delegates.h>
#include <hostfxr.h>
Te pliki można znaleźć w następujących lokalizacjach:
- https://github.com/dotnet/runtime/blob/main/src/native/corehost/nethost/nethost.h
- https://github.com/dotnet/runtime/blob/main/src/native/corehost/coreclr_delegates.h
- https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h
Albo, jeśli masz zainstalowany zestaw SDK platformy .NET 8 w systemie Windows:
C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Host.win-x64\8.0.4\runtimes\win-x64\native
Krok 2. Inicjowanie i uruchamianie środowiska uruchomieniowego platformy .NET
Funkcje hostfxr_initialize_for_runtime_config
i hostfxr_get_runtime_delegate
inicjują i uruchamiają środowisko uruchomieniowe platformy .NET przy użyciu konfiguracji środowiska uruchomieniowego dla składnika zarządzanego, który zostanie załadowany. Funkcja hostfxr_get_runtime_delegate
służy do pobierania delegata środowiska uruchomieniowego, który umożliwia ładowanie zarządzanego zestawu i pobieranie wskaźnika funkcji do metody statycznej w tym zestawie.
// Load and initialize .NET Core and get desired function pointer for scenario
load_assembly_and_get_function_pointer_fn get_dotnet_load_assembly(const char_t *config_path)
{
// Load .NET Core
void *load_assembly_and_get_function_pointer = nullptr;
hostfxr_handle cxt = nullptr;
int rc = init_fptr(config_path, nullptr, &cxt);
if (rc != 0 || cxt == nullptr)
{
std::cerr << "Init failed: " << std::hex << std::showbase << rc << std::endl;
close_fptr(cxt);
return nullptr;
}
// Get the load assembly function pointer
rc = get_delegate_fptr(
cxt,
hdt_load_assembly_and_get_function_pointer,
&load_assembly_and_get_function_pointer);
if (rc != 0 || load_assembly_and_get_function_pointer == nullptr)
std::cerr << "Get delegate failed: " << std::hex << std::showbase << rc << std::endl;
close_fptr(cxt);
return (load_assembly_and_get_function_pointer_fn)load_assembly_and_get_function_pointer;
}
Krok 3. Ładowanie zarządzanego zestawu i pobieranie wskaźnika funkcji do metody zarządzanej
Delegat uruchomieniowy jest wywoływany w celu załadowania zarządzanego zestawu i pobrania wskaźnika funkcji do metody zarządzanej. Delegat wymaga ścieżki zestawu, nazwy typu i nazwy metody jako danych wejściowych i zwraca wskaźnik funkcji, który może służyć do wywoływania metody zarządzanej.
// Function pointer to managed delegate
component_entry_point_fn hello = nullptr;
int rc = load_assembly_and_get_function_pointer(
dotnetlib_path.c_str(),
dotnet_type,
dotnet_type_method,
nullptr /*delegate_type_name*/,
nullptr,
(void**)&hello);
Przekazując nullptr
jako nazwę typu delegata podczas wywoływania delegata środowiska uruchomieniowego, przykład używa domyślnej sygnatury dla metody zarządzanej.
public delegate int ComponentEntryPoint(IntPtr args, int sizeBytes);
Inny podpis można użyć, określając nazwę typu delegata podczas wywoływania delegata w środowisku uruchomieniowym.
Krok 4. Uruchamianie kodu zarządzanego!
Host macierzysty może teraz wywołać metodę zarządzaną i przekazać jej żądane parametry.
lib_args args
{
STR("from host!"),
i
};
hello(&args, sizeof(args));
Ograniczenia
W jednym procesie można załadować tylko jedno środowisko uruchomieniowe.
hostfxr_initialize_for_runtime_config
Jeśli interfejs API jest wywoływany, gdy środowisko uruchomieniowe jest już załadowane, sprawdzi, czy istniejące środowisko uruchomieniowe jest zgodne z określonymi parametrami inicjowania. Jeśli jest to zgodne, istniejące środowisko uruchomieniowe zostanie użyte i jeśli nie jest zgodne, interfejs API zwróci błąd.