C#からWindows API機能を呼び出すとき、どの署名のソースを信頼するか:.NETフレームワークソースコードまたはPinvoke?

StackOverflow https://stackoverflow.com/questions/4305010

質問

たとえば、これは.NETフレームワークソースファイルからです 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フレームワークソースファイルでは、多くの署名があることに気付きました ExactSpelling=true, CharSet=CharSet.Auto, 、しかし、ピンボークではそうではありません。これは必要ですか?

役に立ちましたか?

解決

彼らは両方とも仕事を終わらせるでしょう。ピンボーク猫を皮を剥ぐ方法は複数あります。具体的には、この例については:

  • ExactSpelling=true 最適化であり、Pinvoke Marshallerが探してもらうことを避けます GetWindowRectAGetWindowRectW バージョン。文字列引数を取得しないため、この特定のAPI関数には存在しません。実行時間の実際の違いを見るのは奇跡です。

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

  • [In, Out] それがブリット可能なタイプのデフォルトであるため、不要です。 Pinvoke Marshallerが管理されたメモリへのポインターを直接渡すことができることを意味する高価な単語。変換は必要ありません。可能な限り効率的です。と同じアイデア CharSet しかし、それについて明示的であることは、自己文書化コードを作成し、珍しいケースに対処することを忘れないでください。使用することができる [In] また [Out] 既に最適化されているため、ここではそうではありません。 fwiw、[out]は正しい選択だったでしょう。

  • out vs ref, 、上記と同じアイデア。使用 out APIは実際には内部に渡された値を実際に使用していないため、より正しいです RECT. 。ただし、JITコンパイラは常に構造体を初期化するため、実行時に違いはありません。

  • [return: MarshalAs(UnmanagedType.Bool)] 不要です、それはウィンドウのデフォルトのマーシャリングです BOOL. 。 Pinvoke.netが常にそれを含める理由はわかりません。

したがって、一言で言えば、どちらも完璧ではありませんが、どちらも機能します。これがピンボークの危険です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top