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.
Określa, że funkcja może być wywoływana tylko z kodu zarządzanego. Użyj __clrcall dla wszystkich funkcji wirtualnych, które będą wywoływane tylko z kodu zarządzanego. Nie można jednak używać tej konwencji wywoływania dla funkcji, które będą wywoływane z kodu natywnego. Modyfikator __clrcall jest specyficzny dla firmy Microsoft.
Użyj __clrcall , aby zwiększyć wydajność podczas wywoływania z funkcji zarządzanej do wirtualnej funkcji zarządzanej lub z funkcji zarządzanej do funkcji zarządzanej za pośrednictwem wskaźnika.
Punkty wejścia są oddzielnymi funkcjami generowanymi przez kompilator. Jeśli funkcja ma punkty wejścia natywne i zarządzane, jedna z nich będzie rzeczywistą funkcją z implementacją funkcji. Druga funkcja będzie oddzielną funkcją (thunk), która wywołuje rzeczywistą funkcję i umożliwia środowisku uruchomienioweowi języka wspólnego wykonywanie funkcji PInvoke. Podczas oznaczania funkcji jako __clrcall należy wskazać, że implementacja funkcji musi być MSIL i że funkcja natywnego punktu wejścia nie zostanie wygenerowana.
Jeśli __clrcall nie określono adresu funkcji natywnej, kompilator używa natywnego punktu wejścia. __clrcall wskazuje, że funkcja jest zarządzana i nie trzeba przechodzić przez przejście z zarządzanego na natywny. W takim przypadku kompilator używa zarządzanego punktu wejścia.
Jeśli /clr
(nie /clr:pure
lub /clr:safe
) jest używana i __clrcall nie jest używana, biorąc adres funkcji zawsze zwraca adres natywnej funkcji punktu wejścia. Gdy __clrcall jest używana, natywna funkcja punktu wejścia nie jest tworzona, więc otrzymujesz adres funkcji zarządzanej, a nie funkcję thunk punktu wejścia. Aby uzyskać więcej informacji, zobacz Double Thunking. Opcje kompilatora /clr:pure i /clr:safe są przestarzałe w programie Visual Studio 2015 i nieobsługiwane w programie Visual Studio 2017.
/clr (Kompilacja środowiska uruchomieniowego języka wspólnego) oznacza, że wszystkie funkcje i wskaźniki funkcji są __clrcall, a kompilator nie zezwoli funkcji wewnątrz compiland na oznaczenie niczego innego niż __clrcall. Jeśli /clr:pure jest używany, __clrcall można określić tylko na wskaźnikach funkcji i deklaracjach zewnętrznych.
Funkcje __clrcall można wywoływać bezpośrednio z istniejącego kodu C++, który został skompilowany przy użyciu /clr, o ile ta funkcja ma implementację MSIL. __clrcall funkcje nie mogą być wywoływane bezpośrednio z funkcji, które mają wbudowane funkcje asm i wywołają funkcje wewnętrzne specyficzne dla procesora CPU, na przykład, nawet jeśli te funkcje są kompilowane za pomocą /clr
polecenia .
__clrcall wskaźniki funkcji mają być używane tylko w domenie aplikacji, w której zostały utworzone. Zamiast przekazywać wskaźniki funkcji __clrcall między domenami aplikacji, użyj polecenia CrossAppDomainDelegate. Aby uzyskać więcej informacji, zobacz Domeny aplikacji i Visual C++.
Przykłady
Należy pamiętać, że gdy funkcja zostanie zadeklarowana przy użyciu __clrcall, kod zostanie wygenerowany w razie potrzeby, na przykład po wywołaniu funkcji.
// clrcall2.cpp
// compile with: /clr
using namespace System;
int __clrcall Func1() {
Console::WriteLine("in Func1");
return 0;
}
// Func1 hasn't been used at this point (code has not been generated),
// so runtime returns the address of a stub to the function
int (__clrcall *pf)() = &Func1;
// code calls the function, code generated at difference address
int i = pf(); // comment this line and comparison will pass
int main() {
if (&Func1 == pf)
Console::WriteLine("&Func1 == pf, comparison succeeds");
else
Console::WriteLine("&Func1 != pf, comparison fails");
// even though comparison fails, stub and function call are correct
pf();
Func1();
}
in Func1
&Func1 != pf, comparison fails
in Func1
in Func1
Poniższy przykład pokazuje, że można zdefiniować wskaźnik funkcji, tak aby zadeklarować, że wskaźnik funkcji będzie wywoływany tylko z kodu zarządzanego. Dzięki temu kompilator może bezpośrednio wywołać funkcję zarządzaną i uniknąć natywnego punktu wejścia (problem podwójne thunk).
// clrcall3.cpp
// compile with: /clr
void Test() {
System::Console::WriteLine("in Test");
}
int main() {
void (*pTest)() = &Test;
(*pTest)();
void (__clrcall *pTest2)() = &Test;
(*pTest2)();
}
Zobacz też
Przekazywanie argumentów i konwencje nazewnictwa
Słowa kluczowe