简体   繁体   中英

How do I pass a pointer to a COM interface to a method in C#

I am writing an a small utility app for a class room type of environment. It's purpose is to ensure that all of the systems start each day with the correct baseline for audio capture. The captured audio is in relation to foreign language skills and need to be very consistent. This app will be used in several different classes with upwards of 30 machines each.

I am using C# on Win7 systems to access the Core Audio APIs. Part of what I need was found in a wrapper dll, CoreAudioAPI.dll, which handles MMDevice and EndpointVolume APIs. With that I am able to set the Microphone and speaker volumes.

The last setting I need to set is Microphone Boost which, on most system's UI, shows as a slider for a DB+ value of 0 to 40. In order to get to this setting I needed to add to the existing wrapper dll to access the DeviceTopology API. I have been able to work out everything with this except for one problem. I can get to the setting but to be able to see it's values and set it I have to be able to pass a pointer to one of the interfaces.

I am calling a routine in a separate class that does the work of connecting to the device and finding the setting I need.

Calling line:

mbs.DecibelLevel(ref IAudioVolumeLevel pInterface);

The value passed needs to be a pointer to the interface not a reference to the interface itself.

The work is done here looping through the various topologies until microphone boost is found the line below returns a pointer value for the IAudioVolumeLevel interface that should get passed in from the calling line.

public void DecibelLevel(ref IntPtr audioVolumeLevelPtr)
{
    ...

    _PartNext.Activate(CLSCTX.ALL, ref IID_IAudioVolumeLevel, out audioVolumeLevelPtr);

    ...
}

How do I pass a pointer to IAudioVolumeLevel in C# from the calling routine to the worker routine so I can get and then set this.

Thank you in advance for your help.

EDIT: I tried this example I found to get a pointer object but the second line failed with an 8004:

// Use the CLSID to instantiate the COM object using interop.
Type type = Type.GetTypeFromCLSID(IID_IAudioVolumeLevel);
Object comObj = Activator.CreateInstance(type);

// Return a pointer to the objects IUnknown interface.
IntPtr pIUnk = Marshal.GetIUnknownForObject(comObj);
IntPtr pInterface;

Int32 result = Marshal.QueryInterface(pIUnk, ref IID_IAudioVolumeLevel, out pInterface);

This is supposed to give me a pointer for the other call but is errors on the Activator.CreateInstance call with an 80040154 against the interface. As this is on a basic windows interface to the audio APIs I don't see why any missing components would be the issue.

Help please!

I want to thank those that looked at the question and especially those that provided some feedback. I was able to resolve this initial problem and i am getting the pointer back. It appears that I just had to send and IntPtr as a ref parameter and use that.

That leaves me with one other problem that I haven't yet found a clear answer to. Now that I have my pointer value, how do I use it to get to the actual interface? i have defined the C# interface to be able to access COM:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace CoreAudioApi.Interfaces
{
    [Guid("7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC"),
     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

    public interface IAudioVolumeLevel : IPerChannelDbLevel { }
}

This coorsponds to the COM interface and is how my other interfaces are set up. The C++ example I am working from sends a pointer defined from the interface:

IAudioVolumeLevel* pIaudioVolumeLevel;
getMicrophoneBoostVolumeLevel(defaultDevice, &pIaudioVolumeLevel);

On returning the volume setting for this particular part can be examined and set:

pIaudioVolumeLevel->GetLevelRange(0, &fMinDb, &fMaxDb, &fStepDb);
pIaudioVolumeLevel->GetLevel(0, &pfCurrentDb);
pIaudioVolumeLevel->SetLevel(0, pfCurrentDb, NULL);

Assuming i am getting the correct value in the returned pointer, how do I now set the level through C#?

Thank you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM