1

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

SCardReleaseContext 为例,根据 MSDN 文档,返回类型是LONG。根据这篇 MSDN 文章,c# 的等价物LONGint. 查看 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 自己的站点。

4

3 回答 3

2

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 to uint,类型大小相同,只是值解释不同。

于 2012-04-06T12:27:41.327 回答
1

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

于 2012-04-06T11:46:09.107 回答
1

我会说 MS 在实施时只是弄错了SCardReleaseContextSCardReleaseContext应该声明为 return DWORD。如果我是你,我会简单地将你的 P/invoke 声明为 return uint

于 2012-04-06T11:49:01.350 回答