__clrcall
Microsoft 专用
指定函数只能从托管代码调用。 使用__clrcall对所有虚函数,将只从托管代码调用。 但是,此调用约定不能用于本机代码中调用的函数。
使用__clrcall从托管到托管的虚函数函数或托管函数指针通过托管函数调用时提高性能。
入口点都是独立的、 编译器生成的函数。 如果函数有两个本机和托管入口点,其中之一将是实际的函数实现的功能。 其他函数将是一个单独的函数 (thunk) 连接到实际的功能,并允许公共语言运行库执行 PInvoke 的。 标记为函数时__clrcall,您指定的函数实现必须 MSIL,并且不会生成本机入口点函数。
当获取本机函数的地址,如果__clrcall未指定,则编译器将使用的本机入口点。 __clrcall指示函数托管的并且没有不需要通过从托管到本机。 在这种情况下,编译器使用的托管的入口点。
当**/clr** (不**/clr:pure或/clr:safe**) 使用和__clrcall是未使用,则始终获取函数的地址返回本机入口点函数的地址。 当__clrcall是使用本机入口点函数不会创建,因此您可以获得托管函数,不入口 thunk 函数的地址。 有关更多信息,请参见 双重 Thunk (C++)。
/clr(公共语言运行时编译)表示所有函数和函数指针都是__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();
}
下面的示例显示了您可以定义一个函数指针,,这样,声明该函数指针只能将从托管代码调用。 这样,编译器将直接调用托管的函数,并避免本机入口点 (双形式转换问题)。
// clrcall3.cpp
// compile with: /clr
void Test() {
System::Console::WriteLine("in Test");
}
int main() {
void (*pTest)() = &Test;
(*pTest)();
void (__clrcall *pTest2)() = &Test;
(*pTest2)();
}