已禁用运行时封送

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)
  • inrefout 参数

封送通用类型的默认规则

禁用封送时,默认封送的规则将更改为更简单的规则。 这些规则如下所述。 如 互操作最佳做法文档 所述,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_t ( 对 P/Invoke 上的 CharSet 无影响)
nint System.IntPtr intptr_t
nuint System.UIntPtr uintptr_t
System.Boolean bool
没有 LayoutKind.Auto 字段的用户定义 C# unmanaged 类型 被视为 blittable 类型。 将忽略所有 自定义结构封送
所有其他类型 不受支持

示例

以下示例演示禁用运行时封送时启用或禁用的一些功能。 为了演示本指南的手动应用,这些示例使用 [DllImport],而不是建议的 [LibraryImport] 属性。 使用 [LibraryImport] 时,ID 为 SYSLIB1054 的分析器会提供其他指导。

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