为什么 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自己的网站。
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
.