__clrcall
Microsoft 專有的
指定只可以從 managed 程式碼呼叫函式。使用__clrcall才會從 managed 程式碼呼叫的所有虛擬函式。不過這個呼叫慣例不能用於將會從原生程式碼呼叫的函式。
使用__clrcall來從受管理的函式,以虛擬的 managed 函式或受管理的函式透過指標的 managed 函式呼叫時改善效能。
進入點都是個別的編譯器所產生的函式。如果函式具有兩個原生和 managed 進入點,另一個設定為將會與函式實作實際的函式。此函式會好個別函式 (thunk),執行實際的函式呼叫,並可讓執行 PInvoke common language runtime。在標記為函式時__clrcall,您指定的函式實作必須是 MSIL 和原生進入點函式將不會產生。
當取得原生函式的位址,如果__clrcall未指定,則編譯器會使用原生進入點。__clrcall表示函式的管理,而且沒有經過來回轉換不需要管理到原生。在此情況下編譯器會使用受管理的進入點。
當**/clr** (不**/clr:pure或/clr:safe**) 會使用與__clrcall是未使用,會永遠花費函式的位址傳回原生進入點函式的位址。當__clrcall是使用,原生進入點函式不會建立,因而提供您的 managed 函式沒有進入點函 thunk 式的位址。如需詳細資訊,請參閱 Double Thunking (C++)。
/clr (Common Language Runtime 編譯)所示所有的函式和函式指標都是__clrcall ,並且編譯器不允許函式內部的標記的任何項目而非編譯__clrcall。當**/clr:pure** , __clrcall只能在函式指標和外部宣告上指定。
您可以直接呼叫__clrcall函式從現有的 C++ 程式碼編譯藉由使用**/clr** ,只要該函數語法包含有 MSIL 實作。__clrcall不能直接從內嵌 asm,比方說,呼叫特定 CPU 的 intrinisics 函式呼叫函式,即使這些函式以編譯**/clr**。
__clrcall函式指標只是用於其建立的應用程式定義域中。而不是傳遞的__clrcall函式在應用程式定義域的指標,請使用CrossAppDomainDelegate。如需詳細資訊,請參閱應用程式定義域和 Visual C++。
範例
// clrcall.cpp
// compile with: /clr:oldSyntax /LD
void __clrcall Test1( ) {}
void (__clrcall *fpTest1)( ) = &Test1;
請注意,宣告函式所用__clrcall,必要時,將會產生程式碼 例如,函式會呼叫。
// 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();
}
下列範例會顯示您可以定義函式指標,以致您宣告的函式指標只會叫用的 managed 程式碼。這可讓編譯器直接呼叫 managed 函式,並避免原生進入點 (雙精度浮點的 thunk 問題)。
// clrcall3.cpp
// compile with: /clr
void Test() {
System::Console::WriteLine("in Test");
}
int main() {
void (*pTest)() = &Test;
(*pTest)();
void (__clrcall *pTest2)() = &Test;
(*pTest2)();
}