Udostępnij za pośrednictwem


__clrcall

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ą /clrpolecenia .

__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