2012-02-28 8 views
61

.Netライブラリの多くのメソッドはネイティブコードで実装されています。フレームワーク自体から来たものには[MethodImpl(MethodImplOptions.InternalCall)]とマークされています。いくつかのアンマネージDLLからのものは、[DllImport](例えば、[DllImport("kernel32.dll")])とマークされています。これまでのところ珍しいことはありません。[DllImport( "QCall")]とは何ですか?

しかし、answer for another questionと書いている間に、[DllImport("QCall")]と記された方法がたくさんあることがわかりました。彼らは.Netの内部実装(例えば、GC._Collect())のようです。

私の質問は:正確には[DllImport("QCall")]とは何ですか? [DllImport("QCall")][MethodImpl(MethodImplOptions.InternalCall)]の違いは何ですか?

+1

これは特別な内部コールです。私は詳細を見つけようとしています。 – SLaks

+0

私はしばらく前に "QCall"がclr.dllの一部であることを覚えています。しかし、私はそれ以上のことは知らない。優れた質問のために+1。 – ahawker

+11

これは.NET 4固有の機能です。 V4リファレンスソースから洞察力を得るには、System.Runtime.CompilerServices.Jithelpers.csのソースコードを見てください。文字列は、clr.dll、__IsQCall、およびインラインリテラルとして2回表示されます。これは、MethodImplOptions.InternalCallを超えた拡張メカニズムに非常に似ており、CLRソースコードなしでは難しいことを示しています。 –

答えて

14

これは古いスレッドです。 CoreCLRは現在GitHubでオープンソース化されているため、誰かがまだ答えを求めている場合は、ここでofficial documentationです:私たちは、マネージコードからCLRを呼び出すための2つの技術を持っている

Calling from managed to native code

。 FCallでは、CLRコードを直接呼び出すことができ、オブジェクトの操作に関して多くの柔軟性を提供しますが、オブジェクト参照を正確に追跡しないことでGCホールを発生させるのは簡単です。 QCallを使用すると、P/Invoke経由でCLRを呼び出すことができ、誤って誤って使用することはFCallよりもずっと難しくなります。 FCallはマネージコードでexternメソッドとして識別され、MethodImplOptions.InternalCallビットがセットされます。 QCallは、通常のP/Invokesのように見える静的なexternメソッドですが、 "QCall"というライブラリにあります。

多次元配列要素や範囲チェックなどにアクセスするためのJITヘルパーを実装するためのHCall(Helper呼び出し用)の小さな変形があります.HaallとFCallの唯一の違いは、HCallメソッド例外スタックトレースには表示されません。

そしてそれは小見出しに続く:

例と

35

私はこのことについて.Netチームの何人かに尋ねました。

QCallsは、CLRランタイム内のネイティブメソッドへの呼び出しです。彼らは他の[DllImport]のように振る舞いますが、ネイティブメソッドが行うことに関する特定の(文書化されていない)前提を作るため、より高速です。したがって、さまざまなマーシャリングとGCと例外チェックをスキップできます。

InternalCallは異なります。実行時に生成される特殊な反射スタイルのものが必要です(これはあまり明確ではありません)。

0

補足@SLaks answer、MethodImplOptions.InternalCallについては、ThreadPoolPriority, and MethodImplAttributeで簡単に説明します。

基本的にInternalCallは、ランタイムに、名前付き関数の独自の内部ルックアップテーブルをチェックするように指示します。そのテーブルは、ランタイムコードがコンパイルされたときに明示的に宣言されるランタイムコードのソースファイルのために存在します。これは、すべての内部コールを実装するための関数ポインタのリストを持っています

static ECFunc gGuidFuncs[] = { {FCFuncElement("CompleteGuid", NULL, (LPVOID)GuidNative::CompleteGuid)}, {NULL, NULL, NULL} }; 

この宣言は、管理Guid.CompleteGuidメソッドのメソッド本体が実際にネイティブC++ GuidNative :: CompleteGuid機能で、ランタイムに指示します。この記事では、マーシャリングがどのようにこの場所で動作するかについてはあまり明確ではありませんが、一般的にランタイム実装まではっきりしています。これは、a)関数本体[マーシャリング形式に依存]とb) 。

関連する問題