停用的執行階段封送處理

System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute 屬性套用至組件時,執行階段會針對受控和原生表示法之間的資料封送處理,停用大部分的內建支援。 本文說明停用的功能,以及停用封送處理時 .NET 型別如何對應至原生型別。

停用封送處理的案例

DisableRuntimeMarshallingAttribute 套用至組件時,會影響組件中的 P/Invoke 和委派型別,以及組件中非受控函式指標的任何呼叫。 定義於其他組件中的任何 P/Invoke 或 Interop 委派型別不會受到影響。 也不會停用執行階段內建 COM Interop 支援的封送處理。 內建 COM Interop 支援可以透過功能參數啟用或停用。

停用的功能

DisableRuntimeMarshallingAttribute 套用至組件時,下列屬性將不會有任何作用或擲回例外狀況:

  • P/Invoke 或委派上的 LCIDConversionAttribute
  • P/Invoke 上的 SetLastError=true
  • P/Invoke 上的 ThrowOnUnmappableChar=true
  • P/Invoke 上的 BestFitMapping=true
  • .NET 可變參數引數的方法簽章 (varargs)
  • inrefout 參數

對常見類型進行封送處理的預設規則

停用封送處理時,預設封送處理的規則會變更為更簡單的規則。 以下說明這些規則。 如 Interop 最佳做法文件所述,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
使用者定義的 C# unmanaged 型別,沒有具有 LayoutKind.Auto的欄位 視為 Blittable 型別。 系統會忽略所有自訂結構封送處理
其他型別 不支援

範例

下列範例顯示停用執行階段封送處理時啟用或停用的一些功能:

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