2012-04-06 127 views
0

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

SCardReleaseContext为例,根据MSDN文档,返回类型为LONG。根据this MSDN articleLONG的c#等效值为int。查看SCardReleaseContext的一些p/invoke example signatures,返回类型也被标记为int

但是,WinSCard error codes的定义与int类型不符,因为该值根本不适合int

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

我可以正确地假设C++编译器将取值0x80100001(不适合int),让它溢出,从而将该值转换为一些适当的匹配负值?

另外,我是否正确地说c#编译器不会允许编写这样的错误/缺陷/缺陷,并且处理这个(角落)情况的正确方法是有目的地“制动”p/invoke签名而用uint代替?

编辑:
固定的最后一个环节,这是那种不正确的,在它的值转换为DWORD,这恰好是uint。将链接设置为指向Microsoft自己的站点。

回答

1

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的技术。当然,你必须知道后果。对于谎言LONG没有任何限制,类型具有相同的大小,只有价值解释是不同的。

1

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

+0

DWORD是一个单元,所以你的课程价值非常适合。在我的最后一个链接中,我犯了一个错误,其中的值被转换为DWORD。我现在指向微软自己的网站的链接。我的抱怨是微软声明了int的返回值,但是对于错误代码提供的值不适合int ... – Marko 2012-04-06 12:40:26

+0

@Marko它取决于观点。对我来说它适合int,因为它有32位。 – 2012-04-06 13:16:43

+0

你对这个观点有点正确。但对我来说,微软的观点是有缺陷的。为什么指定一个会溢出数据类型的返回值?为什么不指定一个负值(溢出的结果)开始?指定溢出值是违反直觉的,而不是逻辑的... – Marko 2012-08-29 20:27:40

1

我想说当他们实施SCardReleaseContext时,MS简单地错了,而SCardReleaseContext本应宣布返回DWORD。如果我是你,我会简单地声明你的P/invoke返回uint

相关问题