撰寫 C# DllImport 互操作時,Win32 API 的龐雜類型 (HANDLE、LPSTR、DWORD、WPARAM...) 讓人頭痛。本文整理 `Wtypes.h` 定義的核心非托管類型與 .NET 托管類型的標準對照,作為速查表。
| 非托管類型 (Wtypes.h) | C 語言類型 | .NET 托管類型 | 大小 / 備註 |
|---|---|---|---|
| HANDLE | void* | IntPtr / nint | 32/64 位元自適應,所有句柄通用 |
| BYTE | unsigned char | byte | 8 位元 |
| SHORT | short | short | 16 位元 |
| WORD / USHORT | unsigned short | ushort | 16 位元 |
| INT / LONG | int / long | int | 32 位元 (Win32 long 為 32 位) |
| UINT / ULONG / DWORD | unsigned int / long | uint | 32 位元 |
| BOOL | long | int / bool | 32 位元,非零為真;建議用 int 並自行轉換 |
| FLOAT | float | float | 32 位元 IEEE 754 |
| DOUBLE | double | double | 64 位元 IEEE 754 |
| CHAR | char | sbyte / byte | ANSI 字元,8 位元 |
| WCHAR / OLECHAR | wchar_t | char | Unicode 字元,16 位元 |
| LPSTR / LPCSTR | char* / const char* | string / StringBuilder | [MarshalAs(UnmanagedType.LPStr)] |
| LPWSTR / LPCWSTR | wchar_t* / const wchar_t* | string / StringBuilder | [MarshalAs(UnmanagedType.LPWStr)] 預設 |
| BSTR | wchar_t* (長度前綴) | string | [MarshalAs(UnmanagedType.BStr)] COM 專用 |
| 現象 | 可能原因 | 修正 |
|---|---|---|
| 呼叫後參數值亂碼/錯誤 | CharSet 不匹配導致 ANSI/Unicode 字串解碼錯誤 | 明確指定 CharSet.Ansi 或 Unicode |
| AccessViolationException | 結構體大小/對齊錯誤、陣列長度不足、傳遞 null 給非可空指標 | 檢查 StructLayout.Pack、確保陣列預分配、使用 SafeHandle |
| 64 位元下 Crash | 句柄/指標用 int 而非 IntPtr | 全部改為 IntPtr / nint |
| 回呼不被觸發 | 委派被 GC 回收 | 靜態欄位或 GCHandle.Alloc 持有委派 |
提供更完整的 Win32 API 常見類型對照 (含 `RECT`、`POINT`、`GUID`、`FILETIME`、`VARIANT`、回呼委派等) 及進階封送技巧。