自定义参数封送

当 .NET 运行时的默认参数封送行为不执行所需作时,可以使用该 System.Runtime.InteropServices.MarshalAsAttribute 属性自定义参数封送方式。 禁用 运行时封送时,这些自定义功能不适用。

注释

P/InvokesCOM 的源生成互操作只尊重参数上 MarshalAsAttribute 的小子集。 建议改用 MarshalUsingAttribute 来实现源生成的互操作。 有关详细信息,请参阅源生成的自定义封送

自定义字符串参数

.NET 具有各种格式可用来封送字符串。 这些方法拆分为 C 样式字符串和以 Windows 为中心的字符串格式的不同部分。

C 样式字符串

其中每个格式都将以 null 结尾的字符串传递给本机代码。 它们的差别在于本机字符串的编码。

System.Runtime.InteropServices.UnmanagedType 编码
LPStr ANSI
LPUTF8Str UTF-8
LPWStr UTF-16
LPTStr UTF-16

格式 UnmanagedType.VBByRefStr 略有不同。 与 LPWStr 一样,该格式会将字符串封送到采用 UTF-16 编码的本机 C 样式字符串。 但是,托管签名允许你按引用传入字符串,而匹配的本机签名会按值获取字符串。 这种区别使你能够使用本地 API,该 API 按值获取字符串并就地修改它,而无需使用 StringBuilder。 建议不要手动使用此格式,因为它容易导致与不匹配的本机签名和托管签名混淆。

以 Windows 为中心的字符串格式

与 COM 或 OLE 交互时,可能会发现原生函数使用字符串作为 BSTR 参数。 可以使用 UnmanagedType.BStr 非托管类型将字符串作为 BSTR 进行封送。

如果要与 WinRT API 交互,则可以使用 UnmanagedType.HString 格式将一个字符串封送为 HSTRING 类型。

自定义数组参数

.NET 还为你提供多种管理数组参数的方式。 如果要调用采用 C 样式数组的 API,请使用 UnmanagedType.LPArray 非托管类型。 如果数组中的值需要进行自定义封送,则可以为其使用 [MarshalAs] 属性上的 ArraySubType 字段。

如果使用的是 COM API,则可能必须将数组参数作为 SAFEARRAY* 进行封送。 为此,可以使用 UnmanagedType.SafeArray 非托管类型。 自定义 object 字段上的表中显示了 SAFEARRAY 的元素的默认类型。 可以使用 MarshalAsAttribute.SafeArraySubTypeMarshalAsAttribute.SafeArrayUserDefinedSubType 字段自定义 SAFEARRAY 的确切元素类型。

自定义布尔或十进制参数

有关封送布尔或十进制参数的信息,请参阅 自定义结构封送

自定义对象参数(仅限 Windows)

在 Windows 上,.NET 运行时提供了多种将对象参数封送给本机代码的不同方法。

作为特定的 COM 接口进行封送

如果 API 使用指向 COM 对象的指针,则可以使用类型为 object 的参数上的以下任一 UnmanagedType 格式告知 .NET 作为这些特定接口进行封送:

  • IUnknown
  • IDispatch
  • IInspectable

此外,如果类型标记为 [ComVisible(true)],或如果要封送 object 类型,则可以使用 UnmanagedType.Interface 格式将对象作为类型的 COM 视图的 COM 可调用包装器进行封送。

封送到 VARIANT

如果本机 API 采用 Win32 VARIANT,则可以使用 object 参数上的 UnmanagedType.Struct 格式将对象作为 VARIANT 进行封送。 如需了解 .NET 类型与 VARIANT 类型之间的映射,请参阅有关自定义 object 字段的文档。

自定义封送处理器

如果要将本机 COM 接口投影到其他托管类型,则可以使用 UnmanagedType.CustomMarshaler 格式和 ICustomMarshaler 的实现来提供自己的自定义封送处理代码。