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

时间:2012-04-06 11:43:49

标签: c# pinvoke

有人可以帮我理解为什么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自己的站点。

3 个答案:

答案 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