【问题标题】:How To Marshal Return Values Of WinApi Functions?如何编组 WinApi 函数的返回值?
【发布时间】:2013-07-26 10:33:09
【问题描述】:

简单:如何显式编组 WinAPi 函数的结果?


我知道如何在 C# 中编组 WinApi 函数的参数,但我怎样才能编组返回值?还是我实际上必须编组它们?我了解 WinAPi 仅返回 BOOL 或所有类型的 INT (句柄在非托管代码中也是 int )。
// 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是要走的路。我会记住这一点,并在下次考虑到它。好吗?
  • 您也必须使用适当的字符串类型,否则它将不起作用。那将是 UnmanagedType.LPWStr 用于 Unicode,UnmanagedType.LPTStr 用于 Auto。或者更好的是,完全省略 MarshalAs 属性,只使用默认编组。 CLR 知道它对字符串类型做了什么。

标签: c# winapi marshalling


【解决方案1】:

是的,你可以。你只需要使用[return:]属性语法,例如:

[return: MarshalAs(UnmanagedType.LPStruct)]

但在您的情况下,无需编组。不需要编组来转换这样的整数类型,因此只需在您的示例中使用第二种形式。

如果你真的想要,你可以编写一个名为 GetFileAttributes() 的公共方法来检查返回值的有效性。

【讨论】:

  • 它只适用于非托管类型吗?或者我也可以编组到托管类型?
  • @mini-me MarshalAs 仅适用于 UnmanagedType enum 具有值的类型。
  • 是的,这很明显。但我的意思是编组另一个方向。似乎封送处理仅适用于 from managed to unmanaged 代码。
  • @mini 它双向工作。返回值来自非托管代码到托管代码。 out 参数和StringBuilder 等特殊参数也是如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 2015-11-18
  • 2021-05-09
  • 2018-11-13
  • 1970-01-01
相关资源
最近更新 更多