using System;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SpeechLib {
/// Marshals the COM interface to the .NET Framework interface, and vice versa.
public class EnumeratorToEnumVariantMarshaler : ICustomMarshaler {
[ComImport]
[Guid("00020404-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumVARIANT {
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Next(int celt, [MarshalAs(UnmanagedType.Struct)] out object rgvar, out uint pceltFetched);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Skip(uint celt);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Reset();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[return: MarshalAs(UnmanagedType.Interface)]
IEnumVARIANT Clone();
}
private class VARIANTEnumerator : IEnumerator {
private IEnumVARIANT com_enum;
private object current;
public object Current => current;
public VARIANTEnumerator(IEnumVARIANT com_enum) {
this.com_enum = com_enum;
}
public bool MoveNext() {
uint pceltFetched = 0u;
com_enum.Next(1, out var rgvar, out pceltFetched);
if (pceltFetched == 0) {
return false;
}
current = rgvar;
return true;
}
public void Reset() {
com_enum.Reset();
}
}
private static EnumeratorToEnumVariantMarshaler instance;
/// Performs necessary cleanup of the managed data when it is no longer needed.
/// The managed object to be destroyed.
public void CleanUpManagedData(object pManagedObj) {
throw new NotImplementedException();
}
/// Performs necessary cleanup of the unmanaged data when it is no longer needed.
/// A pointer to the unmanaged data to be destroyed.
public void CleanUpNativeData(IntPtr pNativeData) {
Marshal.Release(pNativeData);
}
/// Returns an instance of the custom marshaler.
/// String "cookie" parameter that can be used by the custom marshaler.
/// An instance of the custom marshaler.
public static ICustomMarshaler GetInstance(string pstrCookie) {
if (instance == null) {
instance = new EnumeratorToEnumVariantMarshaler();
}
return instance;
}
/// Returns the size in bytes of the unmanaged data to be marshaled.
/// -1 to indicate the type this marshaler handles is not a value type.
public int GetNativeDataSize() {
throw new NotImplementedException();
}
/// Marshals an object from managed code to unmanaged code.
/// The managed object to be converted.
/// A pointer to the unmanaged object.
///
/// is .
public IntPtr MarshalManagedToNative(object pManagedObj) {
throw new NotImplementedException();
}
/// Marshals an object from unmanaged code to managed code.
/// A pointer to the unmanaged object to be converted.
/// A managed object.
///
/// is .
/// The unmanaged object that points to could not be converted.
public object MarshalNativeToManaged(IntPtr pNativeData) {
return new VARIANTEnumerator((IEnumVARIANT)Marshal.GetObjectForIUnknown(pNativeData));
}
}
}