using System; using System.Runtime.InteropServices; using Vanara.Extensions; namespace Vanara.InteropServices { /// Marshals strings that are allocated by native code and must be freed after use. /// /// The supplied cookie must be a string representation of a value. If no cookie is supplied, the value /// is used. /// /// The type of the memory allocator. /// /// public class GenericStringMarshaler : GenericStringMarshalerBase where TMem : ISimpleMemoryMethods, new() { private GenericStringMarshaler(CharSet charSet) : base(charSet) { } /// Gets the instance. /// The cookie. /// A new instance of this class. public static ICustomMarshaler GetInstance(string cookie) => new GenericStringMarshaler(CharSetFromString(cookie)); } /// Base abstract class for marshaling strings that are allocated by native code and must be freed after use. /// The type of the memory allocator. /// /// The supplied cookie must be a string representation of a value. If no cookie is supplied, the value /// is used. /// /// public abstract class GenericStringMarshalerBase : ICustomMarshaler where TMem : ISimpleMemoryMethods, new() { private static readonly TMem mem = new(); private readonly CharSet charSet; /// Initializes a new instance of the class. /// The character set. protected GenericStringMarshalerBase(CharSet charSet) => this.charSet = charSet; /// Performs necessary cleanup of the managed data when it is no longer needed. /// The managed object to be destroyed. public virtual void CleanUpManagedData(object ManagedObj) { } /// Performs necessary cleanup of the unmanaged data when it is no longer needed. /// A pointer to the unmanaged data to be destroyed. public virtual void CleanUpNativeData(IntPtr pNativeData) => mem.FreeMem(pNativeData); /// Returns the size of the native data to be marshaled. /// The size in bytes of the native data. public virtual int GetNativeDataSize() => IntPtr.Size; /// Converts the managed data to unmanaged data. /// The managed object to be converted. /// Returns the COM view of the managed object. public virtual IntPtr MarshalManagedToNative(object ManagedObj) => StringHelper.AllocString(ManagedObj as string, charSet, mem.AllocMem); /// Converts the unmanaged data to managed data. /// A pointer to the unmanaged data to be wrapped. /// Returns the managed view of the COM data. public virtual object MarshalNativeToManaged(IntPtr pNativeData) => StringHelper.GetString(pNativeData, charSet); /// Gets the CharSet from a string. /// The string value. /// The default value if is not a valid CharSet. /// A CharSet value. protected static CharSet CharSetFromString(string value, CharSet defaultValue = CharSet.Unicode) { if (!string.IsNullOrEmpty(value)) try { return (CharSet)Enum.Parse(typeof(CharSet), value, true); } catch { } return defaultValue; } } }