20

私はインターネットを広範囲に検索しましたが、適切な説明が見つかりませんでした。

私の質問はとても簡単です。

Initialize という関数を持つ DLL があり、パラメーターの 1 つは、後続の呼び出しで使用されるハンドルを受け取るポインターです。もう 1 つのパラメーターは、完全を期すためにリストする文字列です。私が使用している署名は(単純な形式で)次のとおりです。

[DllImport(MyDll)]
static extern bool Initialize([In] string name, out IntPtr handle);

DLL 自体の署名は次のように記述されています。Initialize(LPTSTR name, HANDLE handle)「HANDLE: ハンドルを受け取る場所へのポインタ」というコメントが含まれています。

そして、その後の呼び出しは次の形式です

[DllImport(MyDll)]
static extern bool DoSomething(IntPtr handle, uint randomParameter);

私は読んでいてSafeHandle、それを使用して IntPtr ハ​​ンドルを代用できるかどうか疑問に思っていました。また、できる場合はどうすればよいですか?抽象 SafeHandle クラスを拡張することは問題ではありませんが、IntPtr を SafeHandle に直接置き換える (そして既定のマーシャリングを使用する) ことはできますか?それとも何か特別なことをする必要がありますか?

4

1 に答える 1

16

SafeHandleとの違いに関するより完全な回答を見つけることができますIntPtr: IntPtr、SafeHandle、HandleRef - 説明

ただし、要約するとIntPtr、引数が実際にマシン サイズのポインターSafeHandleある場合に使用する必要があります。引数が実際に Win32 ハンドルである場合に使用する必要があります。これらのタイプは、一般的に交換可能ではありません。のサイズはIntPtrアーキテクチャによって異なります (x86 では 32 ビット、x64 と amd64 では 64 ビット)。注:カバーの下では、同様にSafeHandleを使用していると思います)。IntPtr

また、 とは異なり、型がガベージ コレクションされると、実際にリソースの破棄が実行されますIntPtrSafeHandleこれにより、プログラムの実行中にシステム リソースがリークしないことが保証されます (ただし、可能な限り早期にインスタンスを作成する必要があります) Dispose()SafeHandle実際には抽象的であることに注意してくださいSafeHandle。これは、適切な廃棄と処理のためにさまざまなアプローチを必要とするさまざまな種類のハンドルがあるためです。

特定のケースでは、呼び出している DLL のドキュメントを確認する必要があります。Win32 DLL の場合は、SafeHandle 型が既に存在している可能性があります。それがサードパーティの DLL である場合は、独自の SafeHandle 実装を展開できます (さらに、 (または同等Initialize()の) バージョンがあることを前提としています)。Release()

IntPtr と SafeHandle に関するその他の興味深い情報は、次の場所にあります。

SafeHandle を使用してネイティブ リソースをカプセル化する

SafeHandle クラス リファレンス

SafeHandles と重要なファイナライズ

于 2012-08-15T16:26:51.650 に答える