已禁用运行时封送

System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute 属性应用于程序集时,运行时将禁用对托管和本机表示形式之间数据封送的大部分内置支持。 本文介绍禁用的功能,以及禁用封送时 .NET 类型如何映射到本机类型。

禁用封送的方案

DisableRuntimeMarshallingAttribute当应用于程序集时,它将影响程序集中的 P/Invokes 和 Delegate 类型,以及对程序集中非托管函数指针的任何调用。 它不会影响其他程序集中定义的任何 P/Invoke 或互操作委托类型。 它还不会为运行时的内置 COM 互操作支持禁用封送。 可以通过 功能交换机启用或禁用内置 COM 互作支持。

禁用的功能

当应用于 DisableRuntimeMarshallingAttribute 程序集时,以下属性将不起作用或引发异常:

  • LCIDConversionAttribute 在 P/Invoke 或委托上
  • SetLastError=true 在 P/Invoke 上
  • ThrowOnUnmappableChar=true 在 P/Invoke 上
  • BestFitMapping=true 在 P/Invoke 上
  • .NET 可变参数方法签名 (varargs)
  • in参数、ref参数、out参数

封送通用类型的默认规则

禁用封送时,默认封送规则将更改为更简单的规则。 下面介绍了这些规则。 如 互操作最佳做法文档 所述,blittable 类型是托管代码和本机代码中布局相同的类型,因此不需要任何封送。 此外,这些规则不能使用 有关自定义参数封送的文档中所述的工具进行自定义

C# 关键字 .NET 类型 原生类型
byte System.Byte uint8_t
sbyte System.SByte int8_t
short System.Int16 int16_t
ushort System.UInt16 uint16_t
int System.Int32 int32_t
uint System.UInt32 uint32_t
long System.Int64 int64_t
ulong System.UInt64 uint64_t
char System.Char char16_tCharSet 对 P/Invoke 无效)
nint System.IntPtr intptr_t
nuint System.UIntPtr uintptr_t
System.Boolean bool
没有 unmanaged 字段的用户定义 LayoutKind.Auto 类型 被视为 blittable 类型。 将忽略所有 自定义结构封送
所有其他类型 不受支持

例子

以下示例展示了在禁用运行时封送时,某些功能的启用或禁用状态。 为了演示本指南的手动应用,这些示例使用 [DllImport] 与建议 [LibraryImport] 的属性相反。 使用 时,ID 为 [LibraryImport] 的分析器会提供其他指导。

using System.Runtime.InteropServices;

struct Unmanaged
{
    int i;
}

[StructLayout(LayoutKind.Auto)]
struct AutoLayout
{
    int i;
}

struct StructWithAutoLayoutField
{
    AutoLayout f;
}

[UnmanagedFunctionPointer] // OK: UnmanagedFunctionPointer attribute is supported
public delegate void Callback();

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] // OK: Specifying a calling convention is supported
public delegate void Callback2(int i); // OK: primitive value types are allowed

[DllImport("NativeLibrary", EntryPoint = "CustomEntryPointName")] // OK: Specifying a custom entry-point name is supported
public static extern void Import(int i);

[DllImport("NativeLibrary", CallingConvention = CallingConvention.Cdecl)] // OK: Specifying a custom calling convention is supported
public static extern void Import(int i);

[UnmanagedCallConv(new[] { typeof(CallConvCdecl) })] // OK: Specifying a custom calling convention is supported
[DllImport("NativeLibrary")]
public static extern void Import(int i);

[DllImport("NativeLibrary", EntryPoint = "CustomEntryPointName", CharSet = CharSet.Unicode, ExactSpelling = false)] // OK: Specifying a custom entry-point name and using CharSet-based lookup is supported
public static extern void Import(int i);

[DllImport("NativeLibrary")] // OK: Not explicitly specifying an entry-point name is supported
public static extern void Import(Unmanaged u); // OK: unmanaged type

[DllImport("NativeLibrary")] // OK: Not explicitly specifying an entry-point name is supported
public static extern void Import(StructWithAutoLayoutField u); // Error: unmanaged type with auto-layout field

[DllImport("NativeLibrary")]
public static extern void Import(Callback callback); // Error: managed types are not supported when runtime marshalling is disabled