本文介绍可用于 .NET 互作源生成器的自定义封送器的不同“形状”。
值封送程序
本部分介绍 .NET 互作源生成器可用于在托管代码和非托管代码之间封送值类型的自定义封送器的形状。
从无状态托管到非托管
使用此形状,生成的代码调用 ConvertToUnmanaged 将值封送到本机代码,或在适用的情况下调用 GetPinnableReference。 生成的代码会在适用情况下调用 Free,这样封送器可以在托管类型的生命周期结束时释放与之关联的任何非托管资源。
[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);
}
}
从无状态托管到非托管,具有调用方分配的缓冲区
使用这种形状,生成器会分配一个指定大小的缓冲区,然后将该缓冲区传递给 ConvertToUnmanaged 方法,以将值封送至本机代码。 生成的代码处理此缓冲区的生存期。
[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);
}
}
从无状态非托管到托管
[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);
}
}
无状态非托管到托管,有保证的取消封送
此形状指示生成器以保证将调用取消封送代码的方式发出,即使前面的封送程序引发了异常,仍确保取消封送会执行。 这对于需要清理或最终完成的类型非常有用,而不管之前作是否成功。
[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);
}
}
无状态双向
此形状既允许托管到非托管的转换,也允许非托管到托管的转换,而封送程序是无状态的。 生成器将使用 ConvertToUnmanaged 方法进行托管到非托管的转换,并使用 ConvertToManaged 方法进行非托管到托管的转换。
[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
}
}
有状态托管到非托管
此形状允许从托管到非托管的有状态封送。 生成的代码将为每个参数使用唯一的封送器实例,以便封送器可以在封送过程中保持状态
[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();
}
}
从有状态托管到非托管,具有调用方分配的缓冲区
此特殊结构允许从托管内存到非托管内存进行有状态的封送处理,生成器会分配一个指定大小的缓冲区并将其传递给 FromManaged 方法。 生成的代码将为每个参数使用唯一的封送器实例,因此封送器可以在封送过程中保持状态。
[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();
}
}
有状态非托管到托管
此形状允许从非托管到托管的有状态取消封送。 生成的代码将为每个参数使用唯一实例,因此结构可以跨非合并保持状态。
[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();
}
}
有状态非托管到托管,有保证的取消封送
此设计允许从非托管到托管的有状态取消封送,生成器确保即使前一个封送程序引发异常,也会调用 ToManagedFinally 方法。 这对于需要清理或最终完成的类型非常有用,而不管之前作是否成功。
[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();
}
}
有状态双向
[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
}
}
集合封送程序
本部分介绍 .NET 互作源生成器支持在托管和非托管代码之间封送集合的自定义集合封送器的形状。 连续集合封送程序用于以非托管表示形式(如数组或列表)表示为连续内存块的集合。
当被封送的集合类型是其元素类型的泛型时(例如 List<T>),自定义封送器类型通常会有两个泛型参数:一个用于托管元素类型,另一个用于非托管元素类型。 如果集合在其元素类型上不是泛型(例如 StringCollection)时,封送处理器可能只有单个用于非托管元素类型的泛型参数。 封送器形状示例演示具有类型TManagedElement元素的非泛型集合TCollection的封送器。 由于元素可能使用不同的值封送程序进行封送;因此它必须是一种针对非托管元素类型 TUnmanagedElement 的泛型。 集合的本机表示形式称为 TNative(通常是 *TUnmanagedElement)。
从无状态托管到非托管
使用此形状,生成器使用静态方法将托管集合封送到非托管内存。 封送器必须提供分配非托管容器、访问托管和非托管元素以及选择性释放非托管资源的方法。
[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);
}
}
从无状态托管到非托管,具有调用方分配的缓冲区
生成器分配缓冲区并将其传递给封送器,以便在封送期间使用。
[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);
}
}
从无状态非托管到托管
此形状将非托管内存转换为托管集合。
[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);
}
}
无状态非托管到托管,有保证的取消封送
生成器确保即使前一个封送程序引发异常,也会发生封送。
[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);
}
}
无状态双向
此形态支持托管到非托管转换和非托管到托管转换。
[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
}
}
有状态托管到非托管
此形状允许封送器在整个封送过程中保持状态。
[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.
}
}
从有状态托管到非托管,具有调用方分配的缓冲区
[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();
}
}
有状态非托管到托管
此形状允许封送程序在整个取消封送过程中保持状态。
[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();
}
}
有状态非托管到托管,有保证的取消封送
[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();
}
}
有状态双向
[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
}
}