Udostępnij przez


Wyłączone marshaling środowiska uruchomieniowego

Po zastosowaniu atrybutu System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute do zestawu środowisko uruchomieniowe wyłącza najbardziej wbudowaną obsługę marshalingu danych między zarządzanymi i natywnymi reprezentacjami. W tym artykule opisano funkcje, które zostały wyłączone i jak typy .NET są mapowane na typy natywne, gdy marshalling jest wyłączony.

Scenariusze, w których marshalling jest wyłączony

Zastosowanie elementu DisableRuntimeMarshallingAttribute do zestawu wpływa na typy P/Invoke i Delegate w zestawie, a także również na wszelkie wywołania niezarządzanych wskaźników funkcji w zestawie. Nie ma to wpływu na żadne typy delegatów P/Invoke ani międzyoperajności zdefiniowane w innych zestawach. Nie wyłącza również marshalingu dla wbudowanej obsługi COM interop środowiska uruchomieniowego. Wbudowana obsługa interop COM może być włączona lub wyłączona przez przełącznik funkcji.

Wyłączone funkcje

Nałożenie DisableRuntimeMarshallingAttribute na zestaw spowoduje, że następujące atrybuty nie będą miały wpływu lub zgłoszą wyjątek:

  • LCIDConversionAttribute w elemecie P/Invoke lub pełnomocniku
  • SetLastError=true na P/Invoke
  • ThrowOnUnmappableChar=true na P/Invoke
  • BestFitMapping=true na P/Invoke
  • Sygnatury metod wariadycznych argumentów w .NET
  • in, ref, out parametry

Domyślne reguły marshalingu typowych typów

Gdy marszaling jest wyłączony, reguły domyślnego marszalingu zmieniają się na znacznie prostsze. Te reguły zostały opisane poniżej. Jak wspomniano w dokumentacji najlepszych rozwiązań międzyoperacyjnych, typy blittable są typami o tym samym układzie w kodzie zarządzanym i natywnym, a w związku z tym nie wymagają żadnego marshallingu. Ponadto tych reguł nie można dostosować za pomocą narzędzi wymienionych w dokumentacji dotyczącej dostosowywania marshalingu parametrów.

Słowo kluczowe języka C# Typ platformy .NET Typ natywny
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 (CharSet na P/Invoke nie ma wpływu)
nint System.IntPtr intptr_t
nuint System.UIntPtr uintptr_t
System.Boolean bool
Typ języka C# unmanaged zdefiniowany przez użytkownika bez pól LayoutKind.Auto Traktowany jako typ kopiowalny w pamięci. Wszystkie dostosowane struktury marcowania są ignorowane.
Wszystkie inne typy Nieobsługiwane

Przykłady

Poniższy przykład pokazuje niektóre funkcje, które są włączone lub wyłączone, gdy marshalling w czasie rzeczywistym jest wyłączony. Aby zademonstrować ręczne stosowanie tych wskazówek, te przykłady używają [DllImport] w przeciwieństwie do zalecanego atrybutu [LibraryImport]. Analizator o identyfikatorze SYSLIB1054 dostarcza dodatkowych wskazówek podczas korzystania z [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