/// <summary> /// Inits the vTable method from GUID. This is a tricky part of this class. /// </summary> /// <param name="ASIOGuid">The ASIO GUID.</param> private void initFromGuid(Guid ASIOGuid) { const uint CLSCTX_INPROC_SERVER = 1; // Start to query the virtual table a index 3 (init method of ASIODriver) const int INDEX_VTABLE_FIRST_METHOD = 3; // Pointer to the ASIO object // USE CoCreateInstance instead of builtin COM-Class instantiation, // because the ASIODriver expect to have the ASIOGuid used for both COM Object and COM interface // The CoCreateInstance is working only in STAThread mode. int hresult = CoCreateInstance(ref ASIOGuid, IntPtr.Zero, CLSCTX_INPROC_SERVER, ref ASIOGuid, out pASIOComObject); if (hresult != 0) { throw new COMException("Unable to instantiate ASIO. Check if STAThread is set", hresult); } // The first pointer at the adress of the ASIO Com Object is a pointer to the // C++ Virtual table of the object. // Gets a pointer to VTable. IntPtr pVtable = Marshal.ReadIntPtr(pASIOComObject); // Instantiate our Virtual table mapping asioDriverVTable = new ASIODriverVTable(); // This loop is going to retrieve the pointer from the C++ VirtualTable // and attach an internal delegate in order to call the method on the COM Object. FieldInfo[] fieldInfos = typeof(ASIODriverVTable).GetFields(); for (int i = 0; i < fieldInfos.Length; i++) { FieldInfo fieldInfo = fieldInfos[i]; // Read the method pointer from the VTable IntPtr pPointerToMethodInVTable = Marshal.ReadIntPtr(pVtable, (i + INDEX_VTABLE_FIRST_METHOD) * IntPtr.Size); // Instantiate a delegate object methodDelegate = Marshal.GetDelegateForFunctionPointer(pPointerToMethodInVTable, fieldInfo.FieldType); // Store the delegate in our C# VTable fieldInfo.SetValue(asioDriverVTable, methodDelegate); } }
/// <summary> /// Inits the vTable method from GUID. This is a tricky part of this class. /// </summary> /// <param name="ASIOGuid">The ASIO GUID.</param> private void initFromGuid(Guid ASIOGuid) { const uint CLSCTX_INPROC_SERVER = 1; // Start to query the virtual table a index 3 (init method of ASIODriver) const int INDEX_VTABLE_FIRST_METHOD = 3; // Pointer to the ASIO object // USE CoCreateInstance instead of builtin COM-Class instantiation, // because the ASIODriver expect to have the ASIOGuid used for both COM Object and COM interface // The CoCreateInstance is working only in STAThread mode. int hresult = CoCreateInstance(ref ASIOGuid, IntPtr.Zero, CLSCTX_INPROC_SERVER, ref ASIOGuid, out pASIOComObject); if ( hresult != 0 ) { throw new COMException("Unable to instantiate ASIO. Check if STAThread is set",hresult); } // The first pointer at the adress of the ASIO Com Object is a pointer to the // C++ Virtual table of the object. // Gets a pointer to VTable. IntPtr pVtable = Marshal.ReadIntPtr(pASIOComObject); // Instantiate our Virtual table mapping asioDriverVTable = new ASIODriverVTable(); // This loop is going to retrieve the pointer from the C++ VirtualTable // and attach an internal delegate in order to call the method on the COM Object. FieldInfo[] fieldInfos = typeof (ASIODriverVTable).GetFields(); for (int i = 0; i < fieldInfos.Length; i++) { FieldInfo fieldInfo = fieldInfos[i]; // Read the method pointer from the VTable IntPtr pPointerToMethodInVTable = Marshal.ReadIntPtr(pVtable, (i + INDEX_VTABLE_FIRST_METHOD) * IntPtr.Size); // Instantiate a delegate object methodDelegate = Marshal.GetDelegateForFunctionPointer(pPointerToMethodInVTable, fieldInfo.FieldType); // Store the delegate in our C# VTable fieldInfo.SetValue(asioDriverVTable, methodDelegate); } }