c# - 从 C# 调用 Windows API 函数时,签名的哪个来源信任 : . NET Framework 源代码或 PInvoke?

标签 c# winapi interop pinvoke 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);

这是来自 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等)

  2. 我注意到在 .NET Framework 源文件中,许多/大多数签名都有 ExactSpelling=true, CharSet=CharSet.Auto,但在 PInvoke 上却没有。这是必需的吗?

最佳答案

他们都会完成工作。给 pinvoke 猫剥皮的方法不止一种。专门针对这个例子:

  • ExactSpelling=true 是一种优化,它避免了让 pinvoke 编码器寻找 GetWindowRectAGetWindowRectW 版本。对于这个特定的 API 函数,它们不存在,因为它不接受字符串参数。看到运行时间的实际差异将是一个奇迹。

  • CharSet=CharSet.Auto 始终是一个好主意,因为默认 (Ansi) 非常低效。它恰好在这里没有任何区别,因为该函数不接受任何字符串参数。

  • [In, Out] 是不必要的,因为这是 blittable 类型的默认值。一个昂贵的词,意思是 pinvoke 编码器可以直接将指针传递给托管内存,不需要转换。尽可能高效。尽管与 CharSet 的想法相同,明确说明它有助于创建 self 记录的代码并记住处理异常情况。能够只使用 [In][Out] 可以是一个重要的优化,只是不在这里,因为它已经被优化了。 Fwiw,[Out] 会是正确的选择。

  • out vs ref,思路同上。使用 out 更为正确,因为 API 实际上并不使用 RECT 中的任何传入值。然而,它在运行时没有任何区别,因为 JIT 编译器无论如何总是初始化一个结构。

  • [return: MarshalAs(UnmanagedType.Bool)] 是不必要的,它是 Windows BOOL 的默认编码(marshal)处理。不确定为什么 pinvoke.net 总是包含它。

所以简而言之,两者都不是完美的,但它们都可以工作。这就是 pinvoke 的危害。

关于c# - 从 C# 调用 Windows API 函数时,签名的哪个来源信任 : . NET Framework 源代码或 PInvoke?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4305010/

相关文章:

c# - 为什么 short(-1) 在 C# 中不等于 -1

c# - Azure 长时间运行的外部 Web 服务调用

windows - Windows API 函数声明中的 "CALLBACK"是什么意思?

c# - Primary Interop Assemblies ( PIA ) 是否需要在机器上安装 Microsoft Office 才能工作

c# - "DateTime?"在 C# 中是什么意思?

c# - 重写分部类中的虚方法

.net - 运行 sn.exe 需要哪些 Windows SDK 部件

c++ - 使用 SDL2 调整无边界窗口大小时出现错误

java - 为什么 Scala 编译器更喜欢将值为 null 的参数推断为 Array[Char] 而不是 Object?

c# - C 字符串文字与 P/Invoke 无法正常工作的 C 字符串数组/指针