__clrcall

Specyficzne dla firmy Microsoft

Określa, że funkcja może zostać wywołana tylko z kodu zarządzanego. Należy użyć __clrcall dla wszystkich funkcji wirtualnych, które będą wywoływane tylko z kodu zarządzanego.Jednakże, niniejsza konwencja wywoływania nie może zostać użyta dla funkcji, które będą wywoływane z kodu natywnego.

Należy używać __clrcall, aby poprawić wydajność podczas wywoływania z funkcji zarządzanej wirtualnej funkcji zarządzanej lub z funkcji zarządzanej funkcji zarządzanej przez wskaźnik.

Punkty wejścia są oddzielnymi, generowanymi przez kompilator funkcjami.Jeśli funkcja ma zarówno natywne, jak i zarządzane punkty wejścia, jedna z nich będzie rzeczywistą funkcją z implementacją funkcji.Druga funkcja będzie oddzielną funkcją (wywołaniem 32-bitowym), która wywołuje rzeczywistą funkcję i umożliwia wykonanie funkcji PInvoke aparatowi plików wykonywalnych języka wspólnego.Oznaczając funkcję jako __clrcall, wskazujemy, że implementacją funkcji musi być MSIL, a natywna funkcja punktu wejścia nie zostanie wygenerowana.

Przy podejmowaniu adresu funkcji natywnej, jeśli __clrcall nie jest określone, kompilator używa natywnego punktu wejścia.__clrcall wskazuje, że funkcja jest zarządzana i nie ma potrzeby przechodzenia z zarządzanej na natywną.W takim przypadku kompilator używa zarządzanego punktu wejścia.

Gdy użyte jest /clr (nie /clr:pure lub /clr:safe) i nie jest użyte __clrcall, pobranie adresu funkcji zawsze zwraca adres natywnej funkcji punktu wejścia.Gdy używane jest __clrcall, natywna funkcja punktu wejścia nie zostanie utworzona, więc zostanie zwrócony adres funkcji zarządzanej, a nie funkcja punktu wejścia wywołania 32-bitowego.Aby uzyskać więcej informacji, zobacz Podwójna konwersja bitowa adresów (C++).

/clr (Kompilacja środowiska uruchomieniowego języka wspólnego) oznacza, że wszystkie funkcje i wskaźniki funkcji mają __clrcall i kompilator nie pozwoli, aby funkcja wewnątrz jednostki kompilacji była oznaczona czymś innym niż __clrcall.Gdy używane jest /clr:pure, __clrcall można określić tylko dla wskaźników funkcji i deklaracji zewnętrznych.

Można bezpośrednio wywołać funkcje __clrcall z istniejącego kodu C++, który został skompilowany przy użyciu /clr, jeżeli ta funkcja ma implementację MSIL.Na przykład funkcje __clrcall nie mogą być wywoływane bezpośrednio z funkcji, które mają w tekście asm i wywołują instrukcje specyficzne dla procesora, nawet jeżeli te funkcję są skompilowane z /clr.

Wskaźniki funkcji __clrcall są przeznaczone wyłącznie do wykorzystania w domenie aplikacji, w której zostały utworzone. Zamiast przekazywać wskaźniki funkcji __clrcall przez domeny aplikacji, należy użyć CrossAppDomainDelegate.Aby uzyskać więcej informacji, zobacz Domeny aplikacji i program Visual C++.

Przykład

// clrcall.cpp
// compile with: /clr:oldSyntax /LD
void __clrcall Test1( ) {}
void (__clrcall *fpTest1)( ) = &Test1;

Należy zauważyć, że kiedy funkcja jest zadeklarowana za pomocą __clrcall, kod zostanie wygenerowany, gdy będzie potrzebny; na przykład, gdy funkcja zostanie wywołana.

// 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 adddress 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();
}
  

W poniższym przykładzie pokazano, że wskaźnik funkcji, można zdefiniować tak, aby zadeklarować, że wskaźnik funkcji zostanie wywołany 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ójnego wywołania 32-bitowego).

// 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ż

Informacje

Przekazywanie argumentów i konwencje nazewnictwa

Słowa kluczowe języka C++