__clrcall

Specifica che una funzione può essere chiamata solo dal codice gestito. Usare __clrcall per tutte le funzioni virtuali che verranno chiamate solo dal codice gestito. Questa convenzione di chiamata, però, non può essere utilizzata per le funzioni che vengono chiamate dal codice nativo. Il modificatore __clrcall è specifico di Microsoft.

Usare __clrcall per migliorare le prestazioni quando si chiama da una funzione gestita a una funzione gestita virtuale o da una funzione gestita a una funzione gestita tramite puntatore.

I punti di ingresso sono funzioni separate e generate dal compilatore. Se una funzione dispone di un punto d'ingresso nativo e uno gestito, uno di essi corrisponde all'effettiva funzione con l'implementazione della funzione. L'altra è una funzione separata (un thunk) che effettua una chiamata nella funzione effettiva e consente a Common Language Runtime di eseguire PInvoke. Quando si contrassegna una funzione come __clrcall, si indica che l'implementazione della funzione deve essere MSIL e che la funzione del punto di ingresso nativo non verrà generata.

Quando si accetta l'indirizzo di una funzione nativa se non viene specificato __clrcall , il compilatore usa il punto di ingresso nativo. __clrcall indica che la funzione è gestita e non è necessario passare attraverso la transizione da gestita a nativa. In questo caso, il compilatore utilizza il punto di ingresso gestito.

Quando /clr viene usato (non /clr:pure o /clr:safe) e non viene usato __clrcall , accettando l'indirizzo di una funzione restituisce sempre l'indirizzo della funzione del punto di ingresso nativo. Quando si usa __clrcall , la funzione del punto di ingresso nativo non viene creata, quindi si ottiene l'indirizzo della funzione gestita, non una funzione del punto di ingresso. Per altre informazioni, vedere Double Thunking. Le opzioni del compilatore /clr:pure e /clr:safe sono deprecate in Visual Studio 2015 e non supportate in Visual Studio 2017.

/clr (compilazione Common Language Runtime) implica che tutte le funzioni e i puntatori a funzione sono __clrcall e il compilatore non consentirà a una funzione all'interno del compiland di essere contrassegnata come diversa da __clrcall. Quando si usa /clr:pure , è possibile specificare __clrcall solo nei puntatori a funzione e nelle dichiarazioni esterne.

È possibile chiamare direttamente __clrcall funzioni dal codice C++ esistente compilato usando /clr purché tale funzione abbia un'implementazione MSIL. __clrcall funzioni non possono essere chiamate direttamente da funzioni con asm inline e chiamare intrinseci specifici della CPU, ad esempio, anche se tali funzioni vengono compilate con /clr.

__clrcall puntatori a funzione devono essere usati solo nel dominio dell'applicazione in cui sono stati creati. Anziché passare __clrcall puntatori a funzione tra domini applicazione, usare CrossAppDomainDelegate. Per altre informazioni, vedere Domini applicazione e Visual C++.

Esempi

Si noti che quando una funzione viene dichiarata con __clrcall, il codice verrà generato quando necessario, ad esempio quando viene chiamata la funzione.

// 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();
}
in Func1
&Func1 != pf, comparison fails
in Func1
in Func1

L'esempio seguente dimostra che è possibile definire un puntatore a funzione in modo da dichiarare, ad esempio, che il puntatore a funzione verrà richiamato solo dal codice gestito. Ciò consente al compilatore di chiamare direttamente la funzione gestita ed evitare il punto di ingresso nativo (problema del doppio thunk).

// clrcall3.cpp
// compile with: /clr
void Test() {
   System::Console::WriteLine("in Test");
}

int main() {
   void (*pTest)() = &Test;
   (*pTest)();

   void (__clrcall *pTest2)() = &Test;
   (*pTest2)();
}

Vedi anche

Passaggio di argomenti e convenzioni di denominazione
Parole chiave