P/Invoke 在默认封送(marshalling)规则下,常见托管 ⇄ 非托管类型的对应关系
下表整理了 P/Invoke 在默认封送(marshalling)规则下,常见托管 ⇄ 非托管类型的对应关系。
内容主要依据微软官方 Marshalling Data with Platform Invoke 文档,并补充了常见指针/句柄用法与字符串缓冲区(StringBuilder
)注意事项。(learn.microsoft.com, learn.microsoft.com)
常见基础数值与指针类型映射
Windows / Win32 类型 | C / C++ 类型 | C# 托管类型 | 说明 |
---|---|---|---|
VOID | void | void | 用于无返回值函数 |
HANDLE | void* | IntPtr / UIntPtr | 平台相关指针大小 |
BYTE | unsigned char | byte | |
SHORT | short | short (Int16 ) | |
WORD | unsigned short | ushort (UInt16 ) | |
INT / LONG | int / long (32‑bit) | int (Int32 ) | |
UINT / DWORD / ULONG | unsigned int / long | uint (UInt32 ) | |
BOOL | long (Win32) | bool / int | 4 字节;返回值时多用 bool |
FLOAT | float | float (Single ) | |
DOUBLE | double | double | |
SIZE_T | size_t | UIntPtr | 平台相关大小 |
INT_PTR / LONG_PTR | intptr_t /long* | IntPtr | |
UINT_PTR | uintptr_t | UIntPtr |
提示:所有以
…_PTR
结尾的 Windows 类型(如HINSTANCE
,LPARAM
等)在 C# 中一般使用IntPtr
;这样无论 x86 还是 x64 都能正确扩展。(stackoverflow.com)
字符与字符串相关映射
Windows / C 类型 | 默认托管类型 | 需要的 CharSet / MarshalAs |
---|---|---|
CHAR | char (System.Char ) | CharSet.Ansi 时为 ANSI,常见于旧 API |
WCHAR | char | CharSet.Unicode 下与 System.Char 对应 |
LPSTR / char* | string 或 StringBuilder | ANSI;[MarshalAs(UnmanagedType.LPStr)] |
LPCSTR / const char* | 同上(只读) | |
LPWSTR / wchar_t* | string / StringBuilder | Unicode;UnmanagedType.LPWStr |
LPCWSTR / const wchar_t* | 同上(只读) |
- 输入字符串:直接用
string
即可,由运行时负责编码转换。 - 输出 / 可读写字符串缓冲区:用
StringBuilder
并在参数前加[Out]
(默认 In/Out)。
但 .NET 9 及最新代码分析规则 CA1838 建议改为手动分配字节缓冲区以减少复制开销。(learn.microsoft.com, learn.microsoft.com)
结构体与数组简表
非托管形态 | 典型托管声明 | 关键属性 |
---|---|---|
纯 POD 结构体(顺序字段) | [StructLayout(LayoutKind.Sequential)] struct Foo { … } | 如有字节对齐需求再加 Pack = N |
结构体指针 | ref Foo / out Foo / IntPtr | ref/out 让 CLR 自动生成 Foo* 指针 |
数组输入 | byte[] data | [In] 可省略 |
数组输出或 In/Out | [Out] byte[] data / IntPtr | 需预分配长度并传入;或用 IntPtr + Marshal.Copy |
若结构体包含指针或可变长成员(如
char*
),建议拆分为“句柄 + 访问函数”的形式而不是直接封送复杂结构。(devblogs.microsoft.com)
获取更多官方资源
- 微软文档: Marshalling Data with Platform Invoke 提供最权威、最完整的类型对照表及示例。(learn.microsoft.com, learn.microsoft.com)
- pinvoke.net: 社区维护的 API 定义仓库,查看具体 Windows 函数的推荐托管签名。(pinvoke.net)
- .NET Blog & DevBlogs: 深入了解各版本运行时对 interop 的改进与性能调优。(devblogs.microsoft.com, devblogs.microsoft.com)
(本篇文章由本人编写,ChatGPT润色)