我正在爲不支持Unicode字符串但支持多字節ANSI字符串的庫的PInvoke包裝器。在調查圖書館的FxCop報告時,我注意到正在使用的字符串編組有一些有趣的副作用。 PInvoke方法使用「最佳擬合」映射來創建單字節ANSI字符串。爲了說明,這是一個方法,看起來像:如何PInvoke多字節ANSI字符串?
[DllImport("thedll.dll", CharSet=CharSet.Ansi)]
public static extern int CreateNewResource(string resourceName);
調用與包含非ASCII字符是Windows找到「關閉」字符的字符串這個函數的結果,通常這看起來像它結束存在 」???」。如果我們假裝'a'是非ASCII字符,那麼傳遞「cat」作爲參數將創建一個名爲「c?t」的資源。
如果我遵循的FxCop規則的指引,我結束了這樣的事情:
[DllImport("thedll.dll", CharSet=CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern int CreateNewResource([MarshalAs(UnmanagedType.LPStr)] string resourceName);
這引入了行爲的改變;現在當一個字符不能被映射時拋出一個異常。這關係到我,因爲這是一個突破性的改變,所以我想嘗試將字符串編組爲多字節ANSI,但是我看不到這樣做的方法。 UnmanagedType.LPStr
被指定爲單字節ANSI字符串LPTStr will be Unicode or ANSI depending on the system, and LPWStr is not what the library expects.
How would I tell PInvoke to marshal the string as a multibyte string? I see there's a
爲我在非託管內存中創建的字符串?看起來,這仍然存在許多當前實現的問題(它仍然可能需要刪除或替換字符),所以我不確定這是否有所改進。我錯過了另一種編組方法嗎?WideCharToMultiByte()
API函數,我是否可以更改簽名以期望IntPtr
我看你是對的;我在當前代碼頁之外進行了字符測試,並且無法想象任何實際上可以在我的代碼頁中工作的多字節字符。我在摸索着試着找到一個代碼頁/字符組合,我可以把它放到函數中來獲得一些信心,但我認爲你是對的。 – OwenP 2009-04-30 19:13:30
我想出瞭如何測試它:我使用了一個用於日文本地化的XP的映像,並設置了一些名稱由大量日文字符組成的資源。這在日本機器上效果很好,但是在英文機器上失敗了。 我會*喜歡*的行爲就好像我使用Unicode一樣,但從您的解釋和實驗中我發現這是不可能的,而且我已經越來越接近它了。我只需等待庫的維護者實現Unicode支持。 – OwenP 2009-04-30 22:10:47