自定义参数封送
当 .NET 运行时的默认参数封送行为不满足要求时,可以使用 System.Runtime.InteropServices.MarshalAsAttribute 属性自定义参数的封送方式。 禁用运行时封送处理时,这些自定义功能不适用。
注意
P/Invokes 和 COM 的源生成互操作只尊重参数上 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.SafeArraySubType 和 MarshalAsAttribute.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 的实现来提供自己的自定义封送处理代码。