从C#调用Windows API函数时,哪个要信任的签名来源:.NET Framework源代码或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. 该功能的正确/最佳签名是哪个? (他们中只有一个 [return: MarshalAs(UnmanagedType.Bool)], , 或者 [In, Out] ref, , ETC。)

  2. 我注意到在.NET框架源文件中,许多/大多数签名都有 ExactSpelling=true, CharSet=CharSet.Auto, ,但在Pinvoke上没有。这需要吗?

有帮助吗?

解决方案

他们都会完成工作。只有一种不止一种方法可以剥皮猫。专门针对此示例:

  • ExactSpelling=true 是一种优化,它避免让Pinvoke Manshaller寻找 GetWindowRectAGetWindowRectW 版本。它们不存在此特定API函数,因为它不使用字符串参数。看到运行时间的实际差异将是一个奇迹。

  • CharSet=CharSet.Auto 始终是一个好主意,因为默认值(ANSI)如此效率低下。碰巧在这里没有任何区别,因为该函数没有任何字符串参数。

  • [In, Out] 是不必要的,因为这是可杀灭类型的默认值。一个昂贵的词,这意味着Pinvoke Manshaller可以直接将指针传递给托管内存,无需转换。尽可能高效。与 CharSet 不过,对其进行明确说明有助于创建自我记录的代码,并记住处理异常情况。只能使用 [In] 或者 [Out] 可以是一个重要的优化,只是在这里不在这里,因为它已经进行了优化。 fwiw,[out]将是正确的选择。

  • out vs ref, ,与上面相同的想法。使用 out 更正确,因为API实际上没有使用任何传递的值 RECT. 。但是,在运行时没有任何区别,因为JIT编译器始终将结构初始化。

  • [return: MarshalAs(UnmanagedType.Bool)] 是不必要的,这是窗口的默认信息 BOOL. 。不知道为什么pinvoke.net总是包含它。

因此,简而言之,两者都不是完美的,但它们俩都会起作用。这就是Pinvoke的危害。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top