For example, this is from .NET Framework source file UnsafeNativeMethods.cs:
[DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)]
public static extern bool GetWindowRect(HandleRef hWnd,
[In, Out] ref NativeMethods.RECT rect);
and this is from PInvoke.Net:
[DllImport("user32.dll")]
[return: MarshalAs(开发者_Python百科UnmanagedType.Bool)]
public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);
Which is the correct/best signature for this function? (only one of them has
[return: MarshalAs(UnmanagedType.Bool)]
, or[In, Out] ref
, etc.)I've noticed that in .NET Framework source files many/most signatures have
ExactSpelling=true, CharSet=CharSet.Auto
, but on PInvoke they don't. Is this required?
They will both get the job done. There's just more than one way to skin a pinvoke cat. Specifically for this example:
ExactSpelling=true
is an optimization, it avoids having the pinvoke marshaller looking for theGetWindowRectA
andGetWindowRectW
versions. They don't exist for this particular API function since it doesn't take a string argument. Seeing an actual difference in run time would be a miracle.CharSet=CharSet.Auto
is always a good idea since the default (Ansi) is so inefficient. It just so happens to not make any difference here since the function doesn't take any string arguments.[In, Out]
is unnecessary because that's the default for a blittable type. An expensive word that means that the pinvoke marshaller can directly pass a pointer to the managed memory, no conversion is required. As efficient as possible. Same idea asCharSet
though, being explicit about it helps to create self-documenting code and to remember to deal with the unusual case. Being able to only use[In]
or[Out]
can be a significant optimization, just not here since it is already optimized. Fwiw, [Out] would have been the correct choice.out
vsref
, same idea as above. Usingout
is more correct since the API doesn't actually use any passed-in values inside theRECT
. It doesn't however make any difference at runtime since the JIT compiler always initializes a struct anyway.[return: MarshalAs(UnmanagedType.Bool)]
is unnecessary, it is the default marshaling for a WindowsBOOL
. Not sure why pinvoke.net always includes it.
So in a nutshell, neither is perfect but they both will work. Such are the hazards of pinvoke.
精彩评论