How To Marshal Return Values Of WinApi Functions?
简单:如何显式编组 WinAPi 函数的结果?
我知道如何在 C# 中编组 WinApi 函数的参数,但我怎样才能编组返回值?还是我实际上必须编组它们?我了解 WinAPi 仅返回 BOOL 或所有类型的 INT (句柄在非托管代码中也是 int )。
1 2 3 4 5 6 7
| // common signature
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
static extern int GetFileAttributes([MarshalAs(UnmanagedType.LPStr)] string filename);
// my prefered signature because easy to handle the result
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
static extern FileAttributes GetFileAttributes([MarshalAs(UnmanagedType.LPStr)] string filename); |
因为 FileAttributes 是枚举并且每个值都可以轻松地转换为 INT 我确信我对这个表示法是安全的。但是我可以像处理参数一样在这个签名中编组结果吗?我其实只知道 Marshal 类和 MarshalAs 属性。
- 你到底为什么要显式调用函数的 ANSI 版本? 1998 年来了,他们想要回他们的代码。
-
@CodyGray 因为谷歌和互联网的其他地方充满了这个功能的 Ansi 版本。我已经制定了所有 3 个版本,但这只是一个示例。
-
我真的不相信,但即使它是真的,那也不是正确的。至少,您需要 CharSet.Auto,但现在没有理由不使用 CharSet.Unicode,除非您的目标是 .NET 2.0 和 Windows 98。
-
这不属于这里,但我一直使用 Ansi 直到今天我终于找到了如何使 Auto 工作。因为它没有。 pinvoke 没有为我的知识提供足够的信息。现在我已经为我的所有 WinApi 文件函数实现了所有 3 个签名,因此我可以在它们之间切换。如果你说Unicode是要走的路。我会记住这一点,并在下次考虑到它。好的 ?
-
您也必须使用适当的字符串类型,否则它将不起作用。 Unicode 是 UnmanagedType.LPWStr,Auto 是 UnmanagedType.LPTStr。或者更好的是,完全省略 MarshalAs 属性,只使用默认编组。 CLR 知道它对字符串类型做了什么。
是的,你可以。您只需要使用 [return:] 属性语法,例如:
1
| [return: MarshalAs(UnmanagedType.LPStruct)] |
但在你的情况下,没有编组要做。不需要编组来转换这样的整数类型,因此只需在示例中使用第二种形式。
如果你真的想要,你可以编写一个名为 GetFileAttributes() 的公共方法来检查返回值的有效性。
- 它只适用于非托管类型吗?或者我也可以编组托管类型?
-
@mini-me MarshalAs 仅适用于 UnmanagedType enum 具有值的类型。
-
是的,这很明显。但我的意思是编组另一个方向。似乎封送处理仅适用于 from managed to unmanaged 代码。
-
@mini 它在两个方向上都有效。返回值来自非托管代码到托管代码。 out 参数以及像 StringBuilder 这样的特殊参数也是如此。