停用的執行階段封送處理
將 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)
in
、ref
、out
參數
對常見類型進行封送處理的預設規則
停用封送處理時,預設封送處理的規則會變更為更簡單的規則。 以下說明這些規則。 如 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 型別。 系統會忽略所有自訂結構封送處理。 | |
其他型別 | 不支援 |
範例
下列範例顯示停用執行階段封送處理時啟用或停用的一些功能。 為了示範本指南的手動應用,這些範例會使用 [DllImport]
,而不是建議的 [LibraryImport]
屬性。 當您使用 [LibraryImport]
時,識別碼為 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