__clrcall__clrcall

関数がマネージド コードからのみ呼び出されることを指定します。Specifies that a function can only be called from managed code. マネージコードからのみ呼び出されるすべての仮想関数には __clrcallを使用します。Use __clrcall for all virtual functions that will only be called from managed code. ただし、この呼び出し規則は、ネイティブ コードから呼び出される関数には使用できません。However this calling convention cannot be used for functions that will be called from native code. __Clrcall修飾子は Microsoft 固有です。The __clrcall modifier is Microsoft-specific.

マネージ関数から仮想マネージ関数への呼び出し時、またはポインターを使用してマネージ関数からマネージ関数への呼び出し時のパフォーマンスを向上させるには、 __clrcallを使用します。Use __clrcall to improve performance when calling from a managed function to a virtual managed function or from managed function to managed function through pointer.

エントリ ポイントはコンパイラが生成した個別の関数です。Entry points are separate, compiler-generated functions. 関数にネイティブ エントリ ポイントとマネージド エントリ ポイントがある場合、そのいずれかが、関数実装を持つ実際の関数になります。If a function has both native and managed entry points, one of them will be the actual function with the function implementation. もう一方の関数は実際の関数に呼び出す別の関数 (サンク) で、共通言語ランタイムに PInvoke を実行させます。The other function will be a separate function (a thunk) that calls into the actual function and lets the common language runtime perform PInvoke. 関数を __clrcallとしてマークする場合は、関数の実装が MSIL である必要があり、ネイティブエントリポイント関数が生成されないことを示します。When marking a function as __clrcall, you indicate the function implementation must be MSIL and that the native entry point function will not be generated.

__Clrcallが指定されていない場合にネイティブ関数のアドレスを取得すると、コンパイラはネイティブエントリポイントを使用します。When taking the address of a native function if __clrcall is not specified, the compiler uses the native entry point. __clrcallは、関数が管理されていて、マネージからネイティブへの遷移を実行する必要がないことを示します。__clrcall indicates that the function is managed and there is no need to go through the transition from managed to native. その場合、コンパイラはマネージド エントリ ポイントを使用します。In that case the compiler uses the managed entry point.

/clr (/clr:pure または /clr:safe) が使用されていて、 __clrcallが使用されていない場合、関数のアドレスを取得すると、常にネイティブエントリポイント関数のアドレスが返されます。When /clr (not /clr:pure or /clr:safe) is used and __clrcall is not used, taking the address of a function always returns the address of the native entry point function. __Clrcallを使用した場合、ネイティブエントリポイント関数は作成されないため、エントリポイントサンク関数ではなく、マネージ関数のアドレスを取得します。When __clrcall is used, the native entry point function is not created, so you get the address of the managed function, not an entry point thunk function. 詳細については、「ダブルサンキング」を参照してください。For more information, see Double Thunking. /Clr: pureおよび /clr: safeコンパイラオプションは visual studio 2015 で非推奨とされており、visual studio 2017 ではサポートされていません。The /clr:pure and /clr:safe compiler options are deprecated in Visual Studio 2015 and unsupported in Visual Studio 2017.

/clr (共通言語ランタイムのコンパイル)は、すべての関数および関数ポインターが __clrcallことを意味します。コンパイラは、コンパイル単位内の関数が __clrcall以外にマークされることを許可しません。/clr (Common Language Runtime Compilation) implies that all functions and function pointers are __clrcall and the compiler will not permit a function inside the compiland to be marked anything other than __clrcall. /Clr: pureを使用する場合、 __clrcallは関数ポインターと外部宣言に対してのみ指定できます。When /clr:pure is used, __clrcall can only be specified on function pointers and external declarations.

関数に MSIL 実装がある限り、 C++ /clrを使用してコンパイルされた既存のコードから __clrcall関数を直接呼び出すことができます。You can directly call __clrcall functions from existing C++ code that was compiled by using /clr as long as that function has an MSIL implementation. __clrcall関数は、インライン asm を持つ関数から直接呼び出すことはできません。また、たとえば、/clrを使用してコンパイルされた関数であっても、CPU 固有の依存関係を呼び出すことはできません。__clrcall functions cannot be called directly from functions that have inline asm and call CPU-specific intrinisics, for example, even if those functions are compiled with /clr.

__clrcall関数ポインターは、それらが作成されたアプリケーションドメインで使用することのみを目的としています。__clrcall function pointers are only meant to be used in the application domain in which they were created. アプリケーションドメイン間で __clrcall関数ポインターを渡す代わりに、CrossAppDomainDelegateを使用します。Instead of passing __clrcall function pointers across application domains, use CrossAppDomainDelegate. 詳細については、「アプリケーションドメインC++とビジュアル」を参照してください。For more information, see Application Domains and Visual C++.

使用例Example

関数が __clrcallで宣言されている場合は、必要に応じてコードが生成されることに注意してください。たとえば、関数が呼び出された場合などです。Note that when a function is declared with __clrcall, code will be generated when needed; for example, when function is called.

// 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

使用例Example

次のサンプルでは、関数ポインターがマネージド コードからのみ呼び出されるように、関数ポインターを定義する方法を示します。The following sample shows that you can define a function pointer, such that, you declare that the function pointer will only be invoked from managed code. これにより、コンパイラはマネージド関数を直接呼び出し、ネイティブ エントリ ポイント (ダブル サンクの問題) を避けることができます。This allows the compiler to directly call the managed function and avoid the native entry point (double thunk issue).

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

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

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

参照See also

引数の渡し規則と名前付け規則Argument Passing and Naming Conventions
キーワードKeywords