P/Invoke 在默认封送(marshalling)规则下,常见托管 ⇄ 非托管类型的对应关系

发布于:2025-07-06 ⋅ 阅读:(18) ⋅ 点赞:(0)

下表整理了 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* stringStringBuilder 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)

获取更多官方资源

(本篇文章由本人编写,ChatGPT润色)


网站公告

今日签到

点亮在社区的每一天
去签到