为什么 Win32 错误代码与方法签名不匹配

本文关键字:不匹配 方法 Win32 错误代码 为什么 | 更新日期: 2023-09-27 18:30:21

有人可以帮助我理解为什么 Win32 错误代码与方法签名不匹配以及处理此问题的正确方法是什么?

以SCardReleaseContext为例,根据MSDN文档,返回类型为LONG。根据这篇 MSDN 文章,LONG 的 c# 等效项是 int 。查看SCardReleaseContext的一些p/invoke示例签名,返回类型也被标记为int

但是,WinSCard 错误代码的定义与int类型不匹配,因为该值根本不适合int

目前,在我的 c# 程序中,我必须将返回值和错误代码值定义为 uint 。这样我的代码就可以编译和工作。否则,编译器会抱怨该值无法转换为 int,例如 - enum ErrorCodes : int { SCARD_E_CANCELLED = 0x80100002 }

我是否可以正确假设 c++ 编译器将获取值0x80100001(不适合 int),让它溢出,从而将值转换为某个适当的匹配负值?

另外,我说 c# 编译器不允许编写这样的错误/错误/缺陷是否正确,处理这种(角落)情况的正确方法是故意"制动"p/invoke 签名并改用uint

编辑:
修复了最后一个链接,这有点不正确,其中的值被转换为DWORD,恰好是uint。将链接设置为指向Microsoft自己的网站。

为什么 Win32 错误代码与方法签名不匹配

winapi被设计为与C编译器一起使用。 一种允许将无符号文本分配给有符号整数的语言。 一些编译器会为此生成警告,但从不生成错误。 您的 C# 编译器不是那么宽容。 您需要应用两个二乘四来保持快乐:

    enum ErrorCodes : int { 
        SCARD_F_INTERNAL_ERROR = unchecked((int)0x80100001) 
    }

更干净的解决方案是让枚举从 uint 继承。

    enum ErrorCodes : uint { 
        SCARD_F_INTERNAL_ERROR = 0x80100001 
    }

并更改 pinvoke 声明以返回 uint 而不是 int。 躺在pinvoke声明中是一种非常常见的技术,特别是对于那些采用PVOID或LPARAM的技术。 当然,你必须知道后果。 没有用于躺长到uint,类型具有相同的大小,只是值解释不同。

为什么它们不适合?例如。(DWORD) 0x80100006适合 32 位。当然,令人困惑的是,在 .NET 中会有负数,但值本身非常适合。最简单的选择是将 P/Invoke 声明更改为 uint,是的。

我会

说 MS 在实现 SCardReleaseContext 时只是弄错了,应该声明SCardReleaseContext返回DWORD。如果我是你,我会简单地声明你的 P/调用以返回uint.