在網上看到很多網友在.NET程式中調用Win32 API,或者調用自己的VC DLL裡面提供的函數的時候,總是被產生正確的C函數在C#中的正確聲明而困擾,而產生C++中結構體在C#中的聲明 - 天,沒有什麼比這個更讓人噁心的事情了。因為:
1. 如果你的結構體裡麵包含 TCHAR字串成員的話,需要考慮ANSI和Unicode DLL的情形。
2. 如果你的結構體裡麵包含數群組成員,需要考慮定長的數組,而不是對應C#資料類型。
3. 如果你的結構體裡麵包含聯合體(UNION),需要使用Explict選項,如果聯合體裡面又包含結構體。
4. 你還要考慮你的結構體可以同時在32位和64位機上運行。
5. 你還要考慮C編譯器對結構體所作的PADDING的最佳化。
6. 你還要考慮在.NET裡面對結構體的最佳化,例如CLR會將一些.NET struct的成員的次序變換—以便更有效地利用記憶體。
7. 如果你的結構裡面還包含了其他的結構體。
8. 如果你的結構體裡面還包含函數指標……
9. 如果你的結構體裡麵包含函數指標數組。
10. 如果你的結構體裡麵包含了指標……
11. 如果你的結構體裡面有一些成員是被所調用的C函數所設定的。
12. CLR提供了幾種結構體的布局選項,什麼Auto,什麼Explicit,什麼Sequential
13. 有的結構體的情況是上面說的情形的綜合,想想我們的VARIANT結構吧。
如果結構體定義錯誤的話,在使用的時候,CLR只是簡簡單單地拋出一個AccessViolationException,真是叫天天不應,叫地地不靈。
另外還有一種情形就是在C中定義.NET的結構體對應的聲明,這樣C或者C++程式可以使用這個結構,調用.NET的類庫提供的一些函數,這個轉換也是一個痛苦的過程。
看起來微軟自己也是深受.NET蹩腳的P/Invoke支援的毒害,因此無奈之餘發布了P/Invoke Interop Assistant工具,你可以去下面這個連結來下載這個工具:
http://download.microsoft.com/download/f/2/7/f279e71e-efb0-4155-873d-5554a0608523/CLRInsideOut2008_01.exe
實際上這個工具已經開源了,你可以從這裡
http://www.codeplex.com/clrinterop/
下載到它的原始碼。
簡單介紹一下它的用法
自動產生Native函數或者結構在.NET程式中的聲明,切換到“SigImp Translate Snippet”標籤,然後將Native函數或者結構的聲明拷貝到“Native Code Snippet”文字框裡面,然後選中“Auto Generate”對話方塊,點擊“Generate”就可以擷取對應的.NET聲明
尋找Win32 API中在.NET中的聲明,選擇“SigImp Search”,並在“Name”文字框裡面輸入你要尋找的函數或者結構名稱就可以了
驗證或者產生.NET函數(或結構)在C 中的聲明,切換到“SigExp”並且開啟一個包含P/Invoke函數調用的.NET Assembly就可以了,這個程式會顯示對應的C的聲明,並且告訴你C#聲明編寫錯誤的地方.