/// <summary>Marshals data from a managed object to an unmanaged block of memory that is allocated using <paramref name="memAlloc"/>.</summary> /// <typeparam name="T">The type of the managed object.</typeparam> /// <param name="value"> /// A managed object that holds the data to be marshaled. The object must be a structure or an instance of a formatted class. /// </param> /// <param name="memAlloc"> /// The function that allocates the memory for the structure (typically <see cref="Marshal.AllocCoTaskMem(int)"/> or <see cref="Marshal.AllocHGlobal(int)"/>. /// </param> /// <param name="bytesAllocated">The bytes allocated by the <paramref name="memAlloc"/> method.</param> /// <param name="prefixBytes">Number of bytes preceding the trailing strings.</param> /// <returns>A pointer to the memory allocated by <paramref name="memAlloc"/>.</returns> public static IntPtr MarshalToPtr <T>(this T value, Func <int, IntPtr> memAlloc, out int bytesAllocated, int prefixBytes = 0) { if (VanaraMarshaler.CanMarshal(typeof(T), out var marshaler)) { using var mem = marshaler.MarshalManagedToNative(value); var ret = memAlloc(bytesAllocated = mem.Size + prefixBytes); mem.DangerousGetHandle().CopyTo(ret.Offset(prefixBytes), mem.Size); return(ret); } else { var newVal = TrueValue(value, out bytesAllocated); bytesAllocated += prefixBytes; var ret = memAlloc(bytesAllocated); Write(ret, newVal, prefixBytes, bytesAllocated); return(ret); } }
/// <summary>Determines whether this type is marshalable.</summary> /// <param name="type">The type to check.</param> /// <returns><see langword="true"/> if the specified type is marshalable; otherwise, <see langword="false"/>.</returns> public static bool IsMarshalable(this Type type) { var t = type.IsNullable() ? type.GetGenericArguments()[0] : type; return(t.IsSerializable || VanaraMarshaler.CanMarshal(t, out _) || t.IsBlittable()); }