自定义参数封送

当 .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,并对其进行就地修改而无需使用 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 非托管类型。 SAFEARRAY上的表中显示了 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 的实现来提供自己的自定义封送处理代码。