__clrcall

指定函式只可以從 Managed 程式碼呼叫。 針對只會從 Managed 程式碼呼叫的所有虛擬函式,請使用 __clrcall 。 不過,這個呼叫慣例不能用於將會從機器碼呼叫的函式。 __clrcall 修飾詞是 Microsoft 特定的。

使用 __clrcall 來改善從 Managed 函式呼叫虛擬 Managed 函式或透過指標從 Managed 函式到 Managed 函式時的效能。

進入點是編譯器產生的不同函式。 如果函式同時具有原生和 Managed 進入點,則其中一個會是具有函式實作的實際函式。 另一個函式將會是呼叫實際函式內部的另一個函式 (Thunk),並且會讓 Common Language Runtime 執行 PInvoke。 將函式 標示為 __clrcall時,表示函式實作必須是 MSIL,而且不會產生原生進入點函式。

如果未 指定__clrcall ,則取得原生函式的位址時,編譯器會使用原生進入點。 __clrcall表示函式已受到管理,而且不需要進行從 Managed 轉換到原生的轉換。 在這種情況下,編譯器會使用 Managed 進入點。

使用 /clr (不是 /clr:pure/clr:safe ) 且 未使用__clrcall 時,取用函式的位址一律會傳回原生進入點函式的位址。 使用__clrcall ,不會建立原生進入點函式,因此您會取得 Managed 函式的位址,而不是進入點 Thunk 函式。 如需詳細資訊,請參閱 Double Thunking Visual Studio 2015 中已淘汰 /clr:pure /clr:safe 編譯器選項,且 Visual Studio 2017 不支援。

/clr (Common Language Runtime 編譯) 表示所有函式和函式指標都會 __clrcall,編譯器不允許編譯器內的函式,而且除了__clrcall 之外 ,也不會標記任何函式。 使用 /clr:pure __clrcall 只能在函式指標和外部宣告上指定。

只要該函式具有 MSIL 實作,您就可以直接從使用 /clr 編譯的現有 C++ 程式碼呼叫 __clrcall 函式。 __clrcall函式無法直接從具有內嵌 asm 且呼叫 CPU 特定內建函式的函式呼叫,例如,即使這些函式是以 /clr 編譯。

__clrcall函式指標只用于建立它們的應用程式域中。 使用 ,而不是跨應用程式域 CrossAppDomainDelegate 傳遞 __clrcall 函式指標。 如需詳細資訊,請參閱 應用程式域和 Visual C++

範例

請注意,當以 __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();
}
in Func1
&Func1 != pf, comparison fails
in Func1
in 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)();
}

另請參閱

引數傳遞和命名慣例
關鍵字