103 lines
4.0 KiB
C#
103 lines
4.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace SpeechLib {
|
|
/// <summary>Marshals the COM <see langword="IEnumVARIANT" /> interface to the .NET Framework <see cref="T:System.Collections.IEnumerator" /> interface, and vice versa.</summary>
|
|
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;
|
|
|
|
/// <summary>Performs necessary cleanup of the managed data when it is no longer needed.</summary>
|
|
/// <param name="pManagedObj">The managed object to be destroyed.</param>
|
|
public void CleanUpManagedData(object pManagedObj) {
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>Performs necessary cleanup of the unmanaged data when it is no longer needed.</summary>
|
|
/// <param name="pNativeData">A pointer to the unmanaged data to be destroyed.</param>
|
|
public void CleanUpNativeData(IntPtr pNativeData) {
|
|
Marshal.Release(pNativeData);
|
|
}
|
|
|
|
/// <summary>Returns an instance of the custom marshaler.</summary>
|
|
/// <param name="pstrCookie">String "cookie" parameter that can be used by the custom marshaler.</param>
|
|
/// <returns>An instance of the custom marshaler.</returns>
|
|
public static ICustomMarshaler GetInstance(string pstrCookie) {
|
|
if (instance == null) {
|
|
instance = new EnumeratorToEnumVariantMarshaler();
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
/// <summary>Returns the size in bytes of the unmanaged data to be marshaled.</summary>
|
|
/// <returns>-1 to indicate the type this marshaler handles is not a value type.</returns>
|
|
public int GetNativeDataSize() {
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>Marshals an object from managed code to unmanaged code.</summary>
|
|
/// <param name="pManagedObj">The managed object to be converted.</param>
|
|
/// <returns>A pointer to the unmanaged object.</returns>
|
|
/// <exception cref="T:System.ArgumentNullException">
|
|
/// <paramref name="pManagedObj" /> is <see langword="null" />.</exception>
|
|
public IntPtr MarshalManagedToNative(object pManagedObj) {
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>Marshals an object from unmanaged code to managed code.</summary>
|
|
/// <param name="pNativeData">A pointer to the unmanaged object to be converted.</param>
|
|
/// <returns>A managed object.</returns>
|
|
/// <exception cref="T:System.ArgumentNullException">
|
|
/// <paramref name="pNativeData" /> is <see langword="null" />.</exception>
|
|
/// <exception cref="T:System.InvalidCastException">The unmanaged object that <paramref name="pNativeData" /> points to could not be converted.</exception>
|
|
public object MarshalNativeToManaged(IntPtr pNativeData) {
|
|
return new VARIANTEnumerator((IEnumVARIANT)Marshal.GetObjectForIUnknown(pNativeData));
|
|
}
|
|
}
|
|
}
|