6

たとえば、これは .NET Framework ソース ファイルUnsafeNativeMethods.csからのものです。

[DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] 
public static extern bool GetWindowRect(HandleRef hWnd, 
    [In, Out] ref NativeMethods.RECT rect);

これは PInvoke.Net からのものです。

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);
  1. この関数の正しい/最良の署名はどれですか? (そのうちの 1 つだけが[return: MarshalAs(UnmanagedType.Bool)]、または[In, Out] refなどを持っています)

  2. .NET Framework ソース ファイルでは、多くの/ほとんどの署名ExactSpelling=true, CharSet=CharSet.Autoに が含まれていますが、PInvoke には含まれていません。これは必須ですか?

4

1 に答える 1

20

彼らは両方とも仕事を成し遂げます。ピンヴォークの猫の皮を剥ぐ方法は 1 つだけではありません。具体的には、この例では:

  • ExactSpelling=trueは最適化であり、pinvoke マーシャラーがバージョンGetWindowRectAGetWindowRectWバージョンを探すのを回避します。この特定の API 関数は文字列引数を取らないため、これらは存在しません。実行時間の実際の違いを見るのは奇跡です。

  • CharSet=CharSet.Autoデフォルト (Ansi) は非常に非効率的であるため、常に良い考えです。関数は文字列引数を取らないため、ここでは違いはありません。

  • [In, Out] これは blittable 型のデフォルトであるため不要です。pinvoke マーシャラーがマネージ メモリへのポインターを直接渡すことができることを意味する高価な言葉であり、変換は必要ありません。できるだけ効率的に。同じ考えCharSetですが、それについて明示することは、自己文書化コードを作成し、異常なケースに対処することを忘れないようにするのに役立ちます。[In]orのみを使用[Out]できることは、重要な最適化になる可能性がありますが、既に最適化されているため、ここではできません。ふぅ、【アウト】が正解だった。

  • outvs ref、上記と同じ考え方。outAPI は実際には渡された値を 内で使用しないため、を使用する方がより正確RECTです。ただし、JITコンパイラは常に構造体を初期化するため、実行時に違いはありません。

  • [return: MarshalAs(UnmanagedType.Bool)]これは Windows のデフォルトのマーシャリングですBOOL。pinvoke.net に常に含まれている理由がわかりません。

つまり、どちらも完璧ではありませんが、どちらも機能します。これがピンボークの危険性です。

于 2010-11-29T16:03:58.113 に答える