__clrcall

Spécifie qu'une fonction peut uniquement être appelée à partir du code managé. Utilisez __clrcall pour toutes les fonctions virtuelles qui ne seront appelées qu’à partir du code managé. Toutefois, cette convention d’appel ne peut pas être utilisée pour les fonctions qui sont appelées à partir du code natif. Le modificateur __clrcall est spécifique à Microsoft.

Utilisez __clrcall pour améliorer les performances lors de l’appel d’une fonction managée à une fonction managée virtuelle ou d’une fonction managée à une fonction managée via un pointeur.

Les points d'entrée sont des fonctions séparées et générées par le compilateur. Si une fonction a des points d'entrée natifs et managés, l'un d'eux est la fonction réelle avec l'implémentation de fonction. L'autre fonction est une fonction séparée (une conversion de code) qui appelle la fonction réelle et qui laisse le Common Langage Runtime effectuer PInvoke. Lorsque vous marquez une fonction comme __clrcall, vous indiquez que l’implémentation de la fonction doit être MSIL et que la fonction de point d’entrée native n’est pas générée.

Lorsque vous prenez l’adresse d’une fonction native si __clrcall n’est pas spécifié, le compilateur utilise le point d’entrée natif. __clrcall indique que la fonction est gérée et qu’il n’est pas nécessaire de passer de la fonction managée à native. Dans ce cas, le compilateur utilise le point d'entrée managé.

Quand /clr (non /clr:pure ou /clr:safe) est utilisé et __clrcall n’est pas utilisé, la prise de l’adresse d’une fonction retourne toujours l’adresse de la fonction de point d’entrée natif. Lorsque __clrcall est utilisé, la fonction de point d’entrée native n’est pas créée, de sorte que vous obtenez l’adresse de la fonction managée, et non une fonction thunk de point d’entrée. Pour plus d’informations, consultez Double Thunking. Les options du compilateur /clr :pure et /clr :safe sont déconseillées dans Visual Studio 2015 et non prises en charge dans Visual Studio 2017.

/clr (Compilation Common Language Runtime) implique que toutes les fonctions et pointeurs de fonction sont __clrcall et que le compilateur n’autorise pas une fonction à l’intérieur de la compilation à marquer autre chose que __clrcall. Lorsque /clr :pure est utilisé, __clrcall ne peut être spécifié que sur les pointeurs de fonction et les déclarations externes.

Vous pouvez appeler directement des fonctions __clrcall à partir du code C++ existant qui a été compilé à l’aide de /clr tant que cette fonction a une implémentation MSIL. __clrcall fonctions ne peuvent pas être appelées directement à partir de fonctions qui ont des intrinsèques inline asm et appellent des intrinsèques spécifiques au processeur, par exemple, même si ces fonctions sont compilées avec /clr.

__clrcall pointeurs de fonction sont destinés uniquement à être utilisés dans le domaine d’application dans lequel ils ont été créés. Au lieu de passer __clrcall pointeurs de fonction entre les domaines d’application, utilisez CrossAppDomainDelegate. Pour plus d’informations, consultez Domaines d’application et Visual C++.

Exemples

Notez que lorsqu’une fonction est déclarée avec __clrcall, le code est généré lorsque nécessaire ; par exemple, lorsque la fonction est appelée.

// 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'exemple suivant montre que vous pouvez définir un pointeur fonction, de sorte que vous indiquez que le pointeur fonction sera uniquement appelé à partir du code managé. Cela permet au compilateur d'appeler directement la fonction managée et d'éviter le point d'entrée natif (double problème de conversion de code).

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

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

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

Voir aussi

Passage des arguments et conventions de dénomination
Mots clés