【问题标题】:How do I solve this "P/Invoke declarations should be portable"?如何解决这个“P/Invoke 声明应该是可移植的”?
【发布时间】:2012-04-28 09:32:50
【问题描述】:

这段代码:

[DllImport("shell32", CharSet=CharSet.Unicode)]
private static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags);

导致以下代码分析问题:

CA1901 P/Invoke 声明应该是可移植的

正如您在代码中声明的那样,P/Invoke 的返回类型 'IconUtil.SHGetFileInfo(string, uint, out IconUtil.SHFILEINFO, uint, uint)' 在 64 位平台上将是 4 字节宽。这是不对的, 因为这个 API 的实际本机声明表明它应该是 8 64 位平台上的字节宽。查阅 MSDN 平台 SDK 帮助确定应使用哪种数据类型的文档 而不是“int”。

我该怎么办?我试过“咨询 MSDN”,但我不确定这个问题到底意味着什么。


我也在同一行得到这个:

CA1060 将 P/Invokes 移至 NativeMethods 类

因为是 P/Invoke 方法,所以 'IconUtil.SHGetFileInfo(string, uint, out IconUtil.SHFILEINFO, uint, uint)' 应该在一个类中定义 命名为 NativeMethods、SafeNativeMethods 或 UnsafeNativeMethods。

【问题讨论】:

  • 您声明 SHGetFileInfo 为返回 intSHGetFileInfo 是否返回 int?根据 MSDN,它没有。在 x86 上,它已经足够接近了。在 x64 上,它不是。这就是第一条消息的内容。
  • 如有疑问,请查看 Pinvoke.Net - 他们通常会正确签名 - SHGetFileInfo。当然,如果他们确实弄错了签名,回馈也很好,但我认为在这种情况下他们是正确的。
  • CA1060 非常清楚:您已将方法声明放在名为 IconUtil 的类中,但它应该放在名为 NativeMethodsSafeNativeMethodsUnsafeNativeMethods 的类中.查看 MSDN 以了解您应该使用这三个中的哪一个。

标签: c# pinvoke


【解决方案1】:

警告所指的 MSDN 页面是本机函数 SHGetFileInfo 的文档。它给出的签名为:

DWORD_PTR SHGetFileInfo(
  __in     LPCTSTR pszPath,
  DWORD dwFileAttributes,
  __inout  SHFILEINFO *psfi,
  UINT cbFileInfo,
  UINT uFlags
);

所以第一个警告是指DWORD_PTR 是一个指针大小的无符号整数这一事实。这意味着你应该使用UIntPtr

接下来跳出来的是SHFILEINFO结构体被表示为__inout。这意味着您需要通过ref 传递它。

所以 p/invoke 声明应该是:

[DllImport("shell32", CharSet=CharSet.Unicode)]
private static extern UIntPtr SHGetFileInfo(
    string pszPath, 
    uint dwFileAttributes, 
    ref SHFILEINFO psfi, 
    uint cbFileInfo, 
    uint flags
);

最后的警告很容易解决。只需将您的 p/invoke 声明放在名为 NativeMethods 的类中。

【讨论】:

    【解决方案2】:

    我通过将int的返回类型更改为IntPtr解决了第一个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-22
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多