2012-04-06 90 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