using System;
using System.Linq;
using System.Runtime.InteropServices;
using Vanara.Extensions;
namespace Vanara.InteropServices
{
/// Marshals an array of strings to an array of pointers to strings with a NULL pointer at the end of the array.
///
public class StringPtrArrayMarshaler : ICustomMarshaler
{
private readonly CharSet charSet = CharSet.Unicode;
private int memSize = 0;
private StringPtrArrayMarshaler(string cookie)
{
if (string.IsNullOrEmpty(cookie)) return;
try { charSet = (CharSet)Enum.Parse(typeof(CharSet), cookie, true); } catch { }
}
/// Gets the instance.
/// The cookie.
/// A new instance of this class.
public static ICustomMarshaler GetInstance(string cookie) => new StringPtrArrayMarshaler(cookie);
///
void ICustomMarshaler.CleanUpManagedData(object ManagedObj) { }
///
void ICustomMarshaler.CleanUpNativeData(IntPtr pNativeData) => Marshal.FreeCoTaskMem(pNativeData);
///
int ICustomMarshaler.GetNativeDataSize() => memSize;
///
IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj)
{
if (ManagedObj == null) return IntPtr.Zero;
string[] sa = null;
if (ManagedObj is string s)
sa = new string[] { s };
if (ManagedObj is string[] _sa)
sa = _sa;
if (sa == null)
throw new InvalidOperationException($"{nameof(StringPtrArrayMarshaler)} can only marshal object types of {typeof(string)} or {typeof(string[])}.");
return sa.MarshalToPtr(InteropServices.StringListPackMethod.Packed, Marshal.AllocCoTaskMem, out memSize, charSet);
}
///
object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData) => pNativeData.ToStringEnum(pNativeData.GetNulledPtrArrayLength(), charSet).ToArray();
}
}