例如,这来自.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);
[return: MarshalAs(UnmanagedType.Bool)]
或[In, Out] ref
等。)ExactSpelling=true, CharSet=CharSet.Auto
,但是在PInvoke上却没有。这是必需的吗? 最佳答案
他们俩都会把工作做好。剥皮猫是不只一种方法。专门针对此示例:
ExactSpelling=true
是一种优化,它避免了pinvoke编码查找GetWindowRectA
和GetWindowRectW
版本。对于此特定的API函数,它们不存在,因为它不需要字符串参数。看到运行时间的实际差异将是一个奇迹。 CharSet=CharSet.Auto
始终是一个好主意,因为默认设置(Ansi)效率很低。由于该函数不接受任何字符串参数,因此恰好在这里没有任何区别。 [In, Out]
是不必要的,因为这是可蓝变类型的默认设置。一个昂贵的词,意味着pinvoke编码器可以直接将指针传递到托管内存,而无需进行转换。尽可能高效。但是,与CharSet
相同,但要明确,有助于创建自说明代码并记住处理异常情况。只能使用[In]
或[Out]
可能是一项重大的优化,但由于已进行了优化,因此不能在此处使用。首先,[Out]将是正确的选择。 out
与ref
,与上述相同。使用out
更为正确,因为API实际上并未在RECT
内部使用任何传入的值。但是,由于JIT编译器始终会始终初始化结构,因此它在运行时没有任何区别。 [return: MarshalAs(UnmanagedType.Bool)]
是不必要的,它是Windows BOOL
的默认编码(marshal)处理。不知道为什么pinvoke.net总是包含它。 简而言之,两者都不是完美的,但它们都可以工作。这就是惊险的危险。
关于c# - 从C#调用Windows API函数时,哪个签名来源可以信任: . NET Framework源代码或PInvoke?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4305010/