__clrcall
Especifica que uma função só pode ser chamada de um código gerenciado. Use __clrcall para todas as funções virtuais que serão chamadas somente do código gerenciado. No entanto, essa convenção de chamada não pode ser usada para as funções que serão chamadas a partir do código nativo. O modificador de __clrcall é específico da Microsoft.
Use __clrcall para melhorar o desempenho ao chamar de uma função gerenciada em uma função gerenciada virtual ou da função gerenciada para a função gerenciada pelo ponteiro.
Os pontos de entrada são funções separadas geradas pelo compilador. Se uma função tem pontos de entrada nativos e gerenciados, um deles será a função real com a implementação da função. Outra função será uma função separada (uma conversão) que chamará a função real e deixará Common Language Runtime executar PInvoke. Ao marcar uma função como __clrcall, você indica que a implementação da função deverá ser MSIL e que a função nativa do ponto de entrada não será gerada.
Ao colocar o endereço de uma função nativa se __clrcall não for especificado, o compilador usará o ponto de entrada nativo. __clrcall indica que a função é gerenciada e que não há necessidade de passar pela transição de gerenciada a nativa. Nesse caso, o compilador usa o ponto de entrada gerenciado.
Quando /clr
(não /clr:pure
ou /clr:safe
) é usado e __clrcall não é usado, usar o endereço de uma função sempre retorna o endereço da função nativa do ponto de entrada. Quando __clrcall é usado, a função nativa do ponto de entrada não é criada. Assim, você obtém o endereço da função gerenciada, não uma função de conversão do ponto de entrada. Para mais informações, confira Conversão dupla. As opções do compilador /clr:pure e /clr:safe foram preteridas no Visual Studio 2015 são incompatíveis com o Visual Studio 2017.
/clr (Compilação do Common Language Runtime) implica que todas as funções e ponteiros de função são __clrcall e o compilador não permitirá que uma função dentro de compiland seja marcada como algo diferente de __clrcall. Quando /clr:pure é usado, __clrcall, só pode ser especificado em ponteiros da função e em declarações externas.
Você pode chamar diretamente as funções __clrcall de código C++ existente que foi compilado usando /clr, desde que essa função tenha uma implementação de MSIL. __clrcall funções não podem ser chamadas diretamente de funções que têm asm embutido e chamam intrínsecos específicos da CPU, por exemplo, mesmo que essas funções sejam compiladas com /clr
.
Os ponteiros da função __clrcall devem ser usados somente no domínio de aplicativo no qual foram criados. Em vez de transmitir ponteiros da função __clrcall pelos domínios de aplicativo, use CrossAppDomainDelegate. Para mais informações, confira Domínios de aplicativo e Visual C++.
Exemplos
Quando uma função é declarada com __clrcall, o código é gerado quando necessário; por exemplo, quando a função é chamada.
// 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
O exemplo a seguir mostra que você pode definir um ponteiro de função de modo a declarar que o ponteiro de função será invocado apenas de códigos gerenciados. Isso permite que o compilador chame diretamente a função gerenciada e evita o ponto de entrada nativo (problema de duas conversões).
// clrcall3.cpp
// compile with: /clr
void Test() {
System::Console::WriteLine("in Test");
}
int main() {
void (*pTest)() = &Test;
(*pTest)();
void (__clrcall *pTest2)() = &Test;
(*pTest2)();
}
Confira também
Convenções de passagem e nomenclatura de argumentos
Palavras-chave