Ale*_*ang 6 c# pinvoke winapi interop signatures
例如,这是来自.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);
Run Code Online (Sandbox Code Playgroud)
这来自PInvoke.Net:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(HandleRef hwnd, out RECT lpRect);
Run Code Online (Sandbox Code Playgroud)
哪个是此功能的正确/最佳签名?(只有其中一个有[return: MarshalAs(UnmanagedType.Bool)]
,或[In, Out] ref
等)
我注意到在.NET Framework源文件中有很多/大多数签名都有ExactSpelling=true, CharSet=CharSet.Auto
,但是在PInvoke上他们没有.这需要吗?
Han*_*ant 20
他们都会完成工作.只有不止一种方法来修饰一只pinvoke猫.特别针对此示例:
ExactSpelling=true
是一个优化,它避免了pinvoke marshaller寻找GetWindowRectA
和GetWindowRectW
版本.它们不存在于此特定API函数中,因为它不接受字符串参数.看到运行时间的实际差异将是一个奇迹.
CharSet=CharSet.Auto
总是一个好主意,因为默认(Ansi)是如此低效.它恰好在这里没有任何区别,因为函数不接受任何字符串参数.
[In, Out]
是不必要的,因为这是blittable类型的默认值.一个昂贵的词意味着pinvoke marshaller可以直接将指针传递给托管内存,不需要转换.尽可能高效.同样的想法CharSet
,明确它有助于创建自我记录代码,并记住处理不寻常的情况.能够只使用[In]
或[Out]
可以是一个重要的优化,因为它已经优化,所以不在这里.Fwiw,[Out]本来是正确的选择.
out
vs ref
,与上面相同的想法.使用out
更正确,因为API实际上并未使用任何传入的值RECT
.但是它在运行时没有任何区别,因为JIT编译器总是初始化一个struct.
[return: MarshalAs(UnmanagedType.Bool)]
是不必要的,它是Windows的默认封送处理BOOL
.不确定为什么pinvoke.net总是包含它.
简而言之,两者都不是完美的,但它们都会起作用.这就是pinvoke的危害.