Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel werden die verschiedenen "Shapes" von benutzerdefinierten Marshallern beschrieben, die mit dem .NET-Interopquellgenerator verwendet werden können.
Wertmarshaller
In diesem Abschnitt werden die Strukturen von benutzerdefinierten Marshallern beschrieben, die vom .NET-Interop-Quellcode-Generator zum Marshallen von Werttypen zwischen verwaltetem und nicht verwaltetem Code verwendet werden können.
Zustandslos verwaltet zu nicht verwaltet
In dieser Form ruft der generierte Code ConvertToUnmanaged für das Marshallings eines Werts in nativen Code oder GetPinnableReference (sofern relevant) auf. Der generierte Code ruft Free bei Bedarf auf, um es dem Marshaller zu ermöglichen, alle nicht verwalteten Ressourcen freizugeben, die dem verwalteten Typ zugeordnet sind, sobald die Lebensdauer endet.
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
static class TMarshaller
{
public static class ManagedToNative
{
/// <summary>
/// Converts a managed type to an unmanaged representation. May throw exceptions.
/// </summary>
public static TNative ConvertToUnmanaged(TManaged managed);
/// <summary>
/// Optional.
/// Returns a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// </summary>
public static ref TNativeDereferenced GetPinnableReference(TManaged managed);
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the marshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslos verwaltet zu nicht verwaltet mit von der aufrufenden Komponente zugewiesenem Puffer
Mit diesem Format weist der Generator einen Puffer der angegebenen Größe zu und übergibt ihn an die Methode ConvertToUnmanaged, um das Marshalling eines Werts in nativen Code zu veranlassen. Der generierte Code behandelt die Lebensdauer dieses Puffers.
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
static class TMarshaller
{
public static class ManagedToNative
{
/// <summary>
/// The size of the buffer that will be allocated by the generator.
/// </summary>
public static int BufferSize { get; }
/// <summary>
/// Converts a managed type to an unmanaged representation using a caller-allocated buffer.
/// </summary>
public static TNative ConvertToUnmanaged(TManaged managed, Span<byte> callerAllocatedBuffer);
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the marshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslos nicht verwaltet zu verwaltet
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
static class TMarshaller
{
public static class NativeToManaged
{
/// <summary>
/// Converts an unmanaged representation to a managed type. May throw exceptions.
/// </summary>
public static TManaged ConvertToManaged(TNative unmanaged);
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the marshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslos nicht verwaltet zu verwaltet mit garantiertem Rückgängigmachen des Marshallings
Diese Form weist den Generator an, den Code für das Rückgängigmachen des Marshallings so zu generieren, dass der Code für das Rückgängigmachen des Marshallings auch dann aufgerufen wird, wenn ein vorheriger Marshaller eine Ausnahme auslöst. Dies ist nützlich für Typen, die unabhängig vom Erfolg der vorherigen Vorgänge bereinigt oder abgeschlossen werden müssen.
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
static class TMarshaller
{
public static class NativeToManaged
{
/// <summary>
/// Converts an unmanaged representation to a managed type.
/// Should not throw exceptions.
/// </summary>
public static TManaged ConvertToManagedFinally(TNative unmanaged);
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the marshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslose Bidirektionalität
Diese Form ermöglicht Konvertierungen von verwaltet zu nicht verwaltet und umgekehrt bei zustandslosem Marshaller. Der Generator verwendet die Methode ConvertToUnmanaged für Konvertierungen von verwaltet zu nicht verwaltet und ConvertToManaged für Konvertierungen von nicht verwaltet zu verwaltet.
[CustomMarshaller(typeof(TManaged<,,,...>), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
[CustomMarshaller(typeof(TManaged<,,,...>), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))]
[CustomMarshaller(typeof(TManaged<,,,...>), MarshalMode.ElementRef, typeof(Bidirectional))]
static class TMarshaller<T, U, V...>
{
public static class Bidirectional
{
// Include members from each of the following:
// - One Stateless Managed->Unmanaged Value shape
// - One Stateless Unmanaged->Managed Value shape
}
}
Zustandsbehaftet von verwaltet zu nicht verwaltet
Diese Form erlaubt das zustandsbehaftete Marshalling von verwaltet zu nicht verwaltet. Der generierte Code verwendet für jeden Parameter eine eindeutige Marshaller-Instanz, sodass der Marshaller den Zustand über den gesamten Marshaling-Prozess hinweg verwalten kann.
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
static class TMarshaller
{
public struct ManagedToNative // Can be ref struct
{
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public ManagedToNative();
/// <summary>
/// Takes a managed type to be converted to an unmanaged representation in ToUnmanaged or GetPinnableReference.
/// </summary>
public void FromManaged(TManaged managed);
/// <summary>
/// Optional.
/// Returns a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, this method is preferred to ToUnmanaged for marshalling.
/// </summary>
public ref TIgnored GetPinnableReference();
/// <summary>
/// Optional.
/// Returns a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, only this method is called for the marshalling step.
/// May throw exceptions.
/// </summary>
public static ref TOther GetPinnableReference(TManaged managed);
/// <summary>
/// Converts the managed type to an unmanaged representation.
/// May throw exceptions.
/// </summary>
public TNative ToUnmanaged();
/// <summary>
/// Optional.
/// In managed to unmanaged stubs, this method is called after call to the unmanaged code.
/// Must not throw exceptions.
/// </summary>
public void OnInvoked();
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the marshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public void Free();
}
}
Zustandsbehaftet verwaltet zu nicht verwaltet mit von der aufrufenden Komponente zugewiesenem Puffer
Diese Form erlaubt zustandsbehaftetes Marshalling von verwaltet zu nicht verwaltet, während der Generator einen Puffer der angegebenen Größe zuweist und an die Methode FromManaged übergibt. Der generierte Code verwendet eine eindeutige Marshaller-Instanz für jeden Parameter, sodass der Marshaller den Zustand über das Marshalling hinweg aufrechterhalten kann.
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
static class TMarshaller
{
public struct ManagedToNative // Can be ref struct
{
/// <summary>
/// The length of the buffer that will be allocated by the generator.
/// </summary>
public static int BufferSize { get; }
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public ManagedToNative();
/// <summary>
/// Takes a managed type to be converted to an unmanaged representation in ToUnmanaged or GetPinnableReference.
/// May throw exceptions.
/// </summary>
public void FromManaged(TManaged managed, Span<TBuffer> buffer);
/// <summary>
/// Optional.
/// Returns a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, this method is preferred to ToUnmanaged for marshalling.
/// </summary>
public ref TIgnored GetPinnableReference();
/// <summary>
/// Optional.
/// Returns a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, only this method is called for the marshalling step.
/// May throw exceptions.
public static ref TOther GetPinnableReference(TManaged managed);
/// <summary>
/// Returns the unmanaged representation of the managed value.
/// May throw exceptions.
/// </summary>
public TNative ToUnmanaged();
/// <summary>
/// Optional.
/// In managed to unmanaged stubs, this method is called after call to the unmanaged code.
/// Must not throw exceptions.
/// </summary>
public void OnInvoked();
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the marshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public void Free();
}
}
Zustandsbehaftet von nicht verwaltet zu verwaltet
Diese Form erlaubt das zustandsbehaftete Rückgängigmachen des Marshallings von nicht verwaltet zu verwaltet. Der generierte Code verwendet für jeden Parameter eine eindeutige Instanz, sodass die Struktur den Zustand über die Deserialisierung hinweg verwalten kann.
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
static class TMarshaller
{
public struct NativeToManaged // Can be ref struct
{
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public NativeToManaged();
/// <summary>
/// Takes an unmanaged representation to be converted to a managed type in ToManaged.
/// Should not throw exceptions.
/// </summary>
public void FromUnmanaged(TNative unmanaged);
/// <summary>
/// Returns the managed value representation of the unmanaged value.
/// May throw exceptions.
/// </summary>
public TManaged ToManaged();
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the unmarshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public void Free();
}
}
Zustandsbehaftet nicht verwaltet zu verwaltet mit garantiertem Rückgängigmachen des Marshallings
Diese Form ermöglicht das zustandsbehaftete Rückgängigmachen des Marshallings von nicht verwaltet zu verwaltet, während der Generator die Methode ToManagedFinally auch dann aufruft, wenn ein vorhergehender Marshaller eine Ausnahme auslöst. Dies ist nützlich für Typen, die unabhängig vom Erfolg der vorherigen Vorgänge bereinigt oder abgeschlossen werden müssen.
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
static class TMarshaller
{
public struct NativeToManaged // Can be ref struct
{
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public NativeToManaged();
/// <summary>
/// Takes an unmanaged representation to be converted to a managed type in ToManagedFinally.
/// Should not throw exceptions.
/// </summary>
public void FromUnmanaged(TNative unmanaged);
/// <summary>
/// Returns the managed value representation of the unmanaged value.
/// Should not throw exceptions.
/// </summary>
public TManaged ToManagedFinally();
/// <summary>
/// Optional.
/// Frees any unmanaged resources associated with the unmarshalling of the managed type.
/// Must not throw exceptions.
/// </summary>
public void Free();
}
}
Zustandsbehaftet bidirektional
[CustomMarshaller(typeof(TManaged), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
[CustomMarshaller(typeof(TManaged), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))]
static class TMarshaller
{
public struct Bidirectional // Can be ref struct
{
// Include members from each of the following:
// - One Stateful Managed->Unmanaged Value shape
// - One Stateful Unmanaged->Managed Value shape
}
}
Sammlungsverarbeiter
In diesem Abschnitt werden die Shapes von benutzerdefinierten Sammlungs-Marshallern beschrieben, die der .NET-Interopquellengenerator für das Marshallen von Sammlungen zwischen verwaltetem und nicht verwaltetem Code unterstützt. Zusammenhängende Sammlungsmarshaller werden für Sammlungen verwendet, die in ihrer nicht verwalteten Darstellung als zusammenhängender Speicherblock dargestellt werden, wie z. B. Arrays oder Listen.
Wenn der Auflistungstyp, für den das Marshalling durchgeführt wird, gegenüber seinem Elementtyp (z. B. List<T>) generisch ist, verfügt der benutzerdefinierte Marshallertyp normalerweise über zwei generische Parameter: einen für den verwalteten Elementtyp und einen für den nicht verwalteten Elementtyp. In Fällen, in denen die Auflistung nicht generisch für den Elementtyp ist (z. B. StringCollection), verfügt der Marshaller möglicherweise nur über einen einzigen generischen Parameter für den nicht verwalteten Elementtyp. Die Beispiele zur Marshallerform zeigen einen Marshaller für eine nicht generische Auflistung (TCollection) mit Elementen vom Typ TManagedElement. Da das Marshalling der Elemente mit unterschiedlichen Wertmarshallern erfolgen kann, müssen sie gegenüber dem nicht verwalteten Elementtyp (TUnmanagedElement) generisch sein. Die systemeigene Darstellung der Auflistung wird TNative genannt (in der Regel ist dies *TUnmanagedElement).
Zustandslos verwaltet zu nicht verwaltet
Mit dieser Form verwendet der Generator statische Methoden, um das Marshalling einer verwalteten Auflistung in nicht verwalteten Speicher vorzunehmen. Der Marshaller muss Methoden bereitstellen, um den nicht verwalteten Container zuzuweisen, auf verwaltete und nicht verwaltete Elemente zuzugreifen und optional nicht verwaltete Ressourcen freizugeben.
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TCollection), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TCollection), MarshalMode.ElementIn, typeof(ManagedToNative))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public static class ManagedToNative
{
/// <summary>
/// Gets the uninitialized unmanaged container for the elements and assigns the number of elements to numElements.
/// The return value is later passed to GetUnmanagedValuesDestination.
/// </summary>
public static TNative AllocateContainerForUnmanagedElements(TCollection managed, out int numElements);
/// <summary>
/// Gets a span of managed elements in the collection.
/// The elements in this span are marshalled by the element marshaller and put into the unmanaged container.
/// </summary>
public static ReadOnlySpan<TManagedElement> GetManagedValuesSource(TCollection managed);
/// <summary>
/// Gets a span of unmanaged elements from the TNative container.
/// The elements in this span are filled with the marshalled values from the managed collection.
/// </summary>
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative unmanaged, int numElements);
/// <summary>
/// Optional. Returns a pinnable reference to the unmanaged representations of the elements.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// </summary>
public static ref TOther GetPinnableReference(TManaged managed);
/// <summary>
/// Optional. Frees unmanaged resources.
/// Should not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslos verwaltet zu nicht verwaltet mit von der aufrufenden Komponente zugewiesenem Puffer
Der Generator weist einen Puffer zu und übergibt ihn für das Marshalling an den Marshaller.
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TCollection), MarshalMode.ElementIn, typeof(ManagedToNative))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public static class ManagedToNative
{
/// <summary>
/// The length of the buffer that will be allocated by the generated code and passed to AllocateContainerForUnmanagedElements.
/// </summary>
public static int BufferSize { get; }
/// <summary>
/// Creates the unmanaged container using a caller-allocated buffer, and assigns the number of elements in the collection to numElements.
/// The return value is later passed to GetUnmanagedValuesDestination.
/// </summary>
public static TNative AllocateContainerForUnmanagedElements(TCollection managed, Span<TBuffer> buffer, out int numElements);
/// <summary>
/// Gets a span of managed elements in the collection.
/// The elements in this span are marshalled by the element marshaller and put into the unmanaged container.
/// </summary>
public static ReadOnlySpan<TManagedElement> GetManagedValuesSource(TCollection managed);
/// <summary>
/// Gets a span of unmanaged elements from the TNative container.
/// The elements in this span are filled with the marshalled values from the managed collection.
/// </summary>
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative unmanaged, int numElements);
/// <summary>
/// Optional. Returns a pinnable reference to the unmanaged representations of the elements.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// </summary>
public static ref TOther GetPinnableReference(TManaged managed);
/// <summary>
/// Optional. Frees unmanaged resources.
/// Should not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslos nicht verwaltet zu verwaltet
Diese Form überträgt Daten aus nicht verwaltetem Speicher in eine verwaltete Sammlung.
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[CustomMarshaller(typeof(TCollection), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
[CustomMarshaller(typeof(TCollection), MarshalMode.ElementOut, typeof(NativeToManaged))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public static class NativeToManaged
{
/// <summary>
/// Allocates a new collection for unmarshalling.
/// May throw exceptions.
/// </summary>
public static TCollection AllocateContainerForManagedElements(TNative unmanaged, int numElements);
/// <summary>
/// Gets the destination span that unmarshalled managed elements will be written to.
/// May throw exceptions.
/// </summary>
public static Span<TManagedElement> GetManagedValuesDestination(TCollection managed);
/// <summary>
/// Gets the source span of unmanaged elements to unmarshal from.
/// May throw exceptions.
/// </summary>
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative unmanaged, int numElements);
/// <summary>
/// Optional. Frees unmanaged resources.
/// Should not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslos nicht verwaltet zu verwaltet mit garantiertem Rückgängigmachen des Marshallings
Der Generator stellt sicher, dass das Rückgängigmachen des Marshallings auch dann erfolgt, wenn ein vorhergehender Marshaller eine Ausnahme auslöst.
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public static class NativeToManaged
{
/// <summary>
/// Allocates the managed container for the elements.
/// Should not throw exceptions other than OutOfMemoryException.
/// </summary>
public static TCollection AllocateContainerForManagedElementsFinally(TNative unmanaged, int numElements);
/// <summary>
/// Gets the destination span that unmarshalled managed elements will be written to.
/// May throw exceptions.
/// </summary>
public static Span<TManagedElement> GetManagedValuesDestination(TCollection managed);
/// <summary>
/// Gets the source span of unmanaged elements to unmarshal from.
/// May throw exceptions.
/// </summary>
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative unmanaged, int numElements);
/// <summary>
/// Optional. Frees unmanaged resources.
/// Should not throw exceptions.
/// </summary>
public static void Free(TNative unmanaged);
}
}
Zustandslose Bidirektionalität
Diese Form unterstützt sowohl Konvertierungen von verwaltet zu nicht verwaltet als auch von nicht verwaltet zu verwaltet.
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
[CustomMarshaller(typeof(TCollection), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))]
[CustomMarshaller(typeof(TCollection), MarshalMode.ElementRef, typeof(Bidirectional))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public static class Bidirectional
{
// Include members from each of the following:
// - One Stateless Managed->Unmanaged Linear Collection shape
// - One Stateless Unmanaged->Managed Linear Collection shape
}
}
Zustandsbehaftet von verwaltet zu nicht verwaltet
Diese Form ermöglicht es dem Marshaller, den Zustand über den Marshallingprozess aufrechtzuerhalten.
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[CustomMarshaller(typeof(TCollection), MarshalMode.UnmanagedToManagedOut, typeof(ManagedToNative))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public struct ManagedToNative // Can be ref struct
{
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public ManagedToNative(); // Optional, can throw exceptions.
/// <summary>
/// Takes a managed collection to be converted to an unmanaged representation in ToUnmanaged or GetPinnableReference.
/// </summary>
public void FromManaged(TCollection collection); // Can throw exceptions.
/// <summary>
/// Gets the source span of managed elements to marshal.
/// May throw exceptions.
/// </summary>
public ReadOnlySpan<TManagedElement> GetManagedValuesSource(); // Can throw exceptions.
/// <summary>
/// Gets the destination span of unmanaged elements to marshal to.
/// May throw exceptions.
/// </summary>
public Span<TUnmanagedElement> GetUnmanagedValuesDestination(); // Can throw exceptions.
/// <summary>
/// Optional.
/// Gets a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, this method is preferred to ToUnmanaged for marshalling.
/// May throw exceptions.
/// </summary>
public ref TOther GetPinnableReference(); // Optional. Can throw exceptions.
/// <summary>
/// Optional.
/// Gets a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, this method is preferred to the instance version and ToUnmanaged for marshalling.
/// May throw exceptions.
/// </summary>
public static ref TOther GetPinnableReference(TCollection collection); // Optional. Can throw exceptions. Result pinnned and passed to Invoke.
/// <summary>
/// Converts the managed collection to an unmanaged representation.
/// May throw exceptions.
/// </summary>
public TNative ToUnmanaged(); // Can throw exceptions.
/// <summary>
/// Optional.
/// In managed to unmanaged stubs, this method is called after call to the unmanaged code.
/// Must not throw exceptions.
/// </summary>
public void OnInvoked(); // Optional. Should not throw exceptions.
}
}
Zustandsbehaftet verwaltet zu nicht verwaltet mit von der aufrufenden Komponente zugewiesenem Puffer
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public struct ManagedToNative // Can be ref struct
{
/// <summary>
/// The length of the buffer that will be allocated by the generated code and passed to FromManaged.
/// </summary>
public static int BufferSize { get; }
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public ManagedToNative();
/// <summary>
/// Takes a managed collection to be converted to an unmanaged representation in ToUnmanaged or GetPinnableReference.
/// The caller-allocated buffer is passed to this method.
/// </summary>
public void FromManaged(TCollection collection, Span<TBuffer> buffer);
/// <summary>
/// Gets the source span of managed elements to marshal.
/// May throw exceptions.
/// </summary>
public ReadOnlySpan<TManagedElement> GetManagedValuesSource();
/// <summary>
/// Gets the destination span of unmanaged elements to marshal to.
/// May throw exceptions.
/// </summary>
public Span<TUnmanagedElement> GetUnmanagedValuesDestination();
/// <summary>
/// Optional.
/// Gets a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, this method is preferred to ToUnmanaged for marshalling.
/// May throw exceptions.
/// </summary>
public ref TOther GetPinnableReference();
/// <summary>
/// Optional.
/// Gets a pinnable reference to the unmanaged representation.
/// The reference will be pinned and passed as a pointer to the native code.
/// TOther should be a dereferenced type of TNative.
/// For example, if TNative is `int*`, then TOther should be `int`.
/// When applicable, this method is preferred to the instance GetPinnableReference and ToUnmanaged for marshalling.
/// May throw exceptions.
/// </summary>
public static ref TOther GetPinnableReference(TCollection collection);
/// <summary>
/// Converts the managed collection to an unmanaged representation.
/// May throw exceptions.
/// </summary>
public TNative ToUnmanaged();
/// <summary>
/// Optional.
/// In managed to unmanaged stubs, this method is called after call to the unmanaged code.
/// Must not throw exceptions.
/// </summary>
public void OnInvoked();
}
}
Zustandsbehaftet von nicht verwaltet zu verwaltet
Diese Form ermöglicht es dem Marshaller, den Zustand über den Prozess zum Rückgängigmachen des Marshallings aufrechtzuerhalten.
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[CustomMarshaller(typeof(TCollection), MarshalMode.UnmanagedToManagedIn, typeof(NativeToManaged))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public struct NativeToManaged // Can be ref struct
{
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public NativeToManaged();
/// <summary>
/// Takes an unmanaged collection to be converted to a managed representation in ToManaged.
/// Should not throw exceptions.
/// </summary>
public void FromUnmanaged(TNative value);
/// <summary>
/// Gets the source span of unmanaged elements to unmarshal from.
/// May throw exceptions.
/// </summary>
public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int numElements);
/// <summary>
/// Gets the destination span that unmarshalled managed elements will be written to.
/// May throw exceptions.
/// </summary>
public Span<TManagedElement> GetManagedValuesDestination(int numElements);
/// <summary>
/// Returns the managed value representation of the unmanaged value.
/// May throw exceptions.
/// </summary>
public TCollection ToManaged();
/// <summary>
/// Optional. Should not throw exceptions.
/// </summary>
public void Free();
}
}
Zustandsbehaftet nicht verwaltet zu verwaltet mit garantiertem Rückgängigmachen des Marshallings
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedOut, typeof(NativeToManaged))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public struct NativeToManaged // Can be ref struct
{
/// <summary>
/// Optional constructor.
/// May throw exceptions.
/// </summary>
public NativeToManaged(); // Optional, can throw exceptions.
/// <summary>
/// Takes an unmanaged collection to be converted to a managed representation in ToManagedFinally.
/// Should not throw exceptions.
/// </summary>
public void FromUnmanaged(TNative value);
/// <summary>
/// Gets the source span of unmanaged elements to unmarshal from.
/// May throw exceptions.
/// </summary>
public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int numElements);
/// <summary>
/// Gets the destination span that unmarshalled managed elements will be written to.
/// May throw exceptions.
/// </summary>
public Span<TManagedElement> GetManagedValuesDestination(int numElements);
/// <summary>
/// Returns the managed value representation of the unmanaged value.
/// Should not throw exceptions.
/// </summary>
public TCollection ToManagedFinally();
/// <summary>
/// Optional. Should not throw exceptions.
/// </summary>
public void Free();
}
}
Zustandsbehaftet bidirektional
[CustomMarshaller(typeof(TCollection), MarshalMode.ManagedToUnmanagedRef, typeof(Bidirectional))]
[CustomMarshaller(typeof(TCollection), MarshalMode.UnmanagedToManagedRef, typeof(Bidirectional))]
[ContiguousCollectionMarshaller]
static class TMarshaller<TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public struct Bidirectional // Can be ref struct
{
// Include members from each of the following:
// - One Stateful Managed->Unmanaged Contiguous Collection shape
// - One Stateful Unmanaged->Managed Contiguous Collection shape
}
}