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;
}
}
}