/// <summary> /// Allocates memory for the managed representation of the array. /// </summary> /// <param name="unmanaged">The unmanaged array.</param> /// <param name="numElements">The unmanaged element count.</param> /// <returns>The managed array.</returns> public static T *[]? AllocateContainerForManagedElements(TUnmanagedElement *unmanaged, int numElements) { if (unmanaged is null) { return(null); } return(new T *[numElements]); }
/// <summary> /// Initializes the <see cref="PointerArrayMarshaller{T, TUnmanagedElement}.ManagedToUnmanagedIn"/> marshaller. /// </summary> /// <param name="array">The array to be marshalled.</param> /// <param name="buffer">The buffer that may be used for marshalling.</param> /// <remarks> /// The <paramref name="buffer"/> must not be movable - that is, it should not be /// on the managed heap or it should be pinned. /// </remarks> public void FromManaged(T *[]?array, Span <TUnmanagedElement> buffer) { _allocatedMemory = null; if (array is null) { _managedArray = null; _span = default; return; } _managedArray = array; // Always allocate at least one byte when the array is zero-length. if (array.Length <= buffer.Length) { _span = buffer[0..array.Length];
/// <summary> /// Initializes the <see cref="SpanMarshaller{T, TUnmanagedElement}.ManagedToUnmanagedIn"/> marshaller. /// </summary> /// <param name="managed">Span to be marshalled.</param> /// <param name="buffer">Buffer that may be used for marshalling.</param> /// <remarks> /// The <paramref name="buffer"/> must not be movable - that is, it should not be /// on the managed heap or it should be pinned. /// </remarks> public void FromManaged(Span <T> managed, Span <TUnmanagedElement> buffer) { _allocatedMemory = null; // Emulate the pinning behavior: // If the span is over a null reference, then pass a null pointer. if (Unsafe.IsNullRef(ref MemoryMarshal.GetReference(managed))) { _managedArray = null; _span = default; return; } _managedArray = managed; if (managed.Length <= buffer.Length) { _span = buffer[0..managed.Length];
/// <summary> /// Gets a source for the unmanaged elements in the array. /// </summary> /// <param name="unmanagedValue">The unmanaged array to get a source for.</param> /// <param name="numElements">The unmanaged element count.</param> /// <returns>The <see cref="ReadOnlySpan{TUnmanagedElement}"/> containing the unmanaged elements to marshal.</returns> public static ReadOnlySpan <TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement *unmanagedValue, int numElements) => new ReadOnlySpan <TUnmanagedElement>(unmanagedValue, numElements);
/// <summary> /// Gets a destination for the unmanaged elements in the array. /// </summary> /// <param name="unmanaged">The unmanaged allocation to get a destination for.</param> /// <param name="numElements">The unmanaged element count.</param> /// <returns>The <see cref="Span{TUnmanagedElement}"/> of unmanaged elements.</returns> public static Span <TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement *unmanaged, int numElements) => new Span <TUnmanagedElement>(unmanaged, numElements);
/// <summary> /// Frees memory for the unmanaged array. /// </summary> /// <param name="unmanaged">The unmanaged array.</param> public static void Free(TUnmanagedElement *unmanaged) => Marshal.FreeCoTaskMem((IntPtr)unmanaged);