有人可以帮我理解为什么Win32错误代码与方法签名不匹配,处理这个问题的正确方法是什么?
以SCardReleaseContext为例,根据MSDN文档,返回类型为LONG
。根据{{3}},LONG
的c#等效项为int
。查看一些p / invoke this MSDN article的SCardReleaseContext,返回类型也标记为int
。
但是,example signatures的定义与int
类型不匹配,因为该值根本不适合int
。
目前,在我的c#程序中,我必须将返回值和错误代码值定义为uint
。这样我的代码编译和工作。否则,编译器会抱怨该值无法转换为int,例如 - enum ErrorCodes : int { SCARD_E_CANCELLED = 0x80100002 }
。
我是否可以正确地假设c ++编译器将取值0x80100001(不适合int),让它溢出并因此将值转换为适当的匹配负值?
另外,我是否正确地说c#编译器不会允许写入这样的错误/ bug / flaw并且正确处理这个(角落)情况的方法是有目的地“制动”p / invoke签名和请改用uint
?
修改
修复了最后一个不正确的链接,其中值已转换为DWORD
,恰好是uint
。将链接设置为指向Microsoft自己的站点。
答案 0 :(得分:2)
winapi旨在与C编译器一起使用。一种允许将无符号文字指定为有符号整数的语言。有些编译器会为此生成警告但从不出错。你的C#编译器并不那么宽容。你需要两个两个四分之一来保持它的快乐:
enum ErrorCodes : int {
SCARD_F_INTERNAL_ERROR = unchecked((int)0x80100001)
}
更干净的解决方案是让enum继承uint。
enum ErrorCodes : uint {
SCARD_F_INTERNAL_ERROR = 0x80100001
}
并更改pinvoke声明以返回uint而不是int。位于pinvoke声明中是一种非常常见的技术,尤其是采用PVOID或LPARAM的技术。当然,你必须知道后果。 LONG to uint没有,类型具有相同的大小,只有值解释不同。
答案 1 :(得分:1)
他们怎么不适合?例如。 (DWORD)0x80100006适合32位。当然,令人困惑的是你在.NET中会有负数,但价值本身很合适。最简单的选择是将P / Invoke声明更改为uint,是的。
答案 2 :(得分:1)
我说MS在实施SCardReleaseContext
时错误地说错了,SCardReleaseContext
应该被声明为返回DWORD
。如果我是你,我只会声明你的P / invoke返回uint
。