简体   繁体   English

如何将指向COM接口的指针传递给C#中的方法

[英]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. 该应用程序将用于几类不同的类,每类最多可使用30台计算机。

I am using C# on Win7 systems to access the Core Audio APIs. 我在Win7系统上使用C#来访问Core Audio API。 Part of what I need was found in a wrapper dll, CoreAudioAPI.dll, which handles MMDevice and EndpointVolume APIs. 我需要的部分内容是在处理MMDevice和EndpointVolume API的包装dll CoreAudioAPI.dll中找到的。 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. 我需要设置的最后一个设置是Microphone Boost,在大多数系统的UI上,它显示为DB +值从0到40的滑块。为了达到此设置,我需要添加到现有的包装dll中以访问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. 在这里完成工作,循环遍历各种拓扑,直到找到麦克风增强,下面的行为IAudioVolumeLevel接口返回了一个指针值,该值应该从调用行中传入。

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. 如何将C#中的IAudioVolumeLevel指针从调用例程传递到工作例程,以便我可以获取然后进行设置。

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: 编辑:我尝试过这个示例,我发现获得了一个指针对象,但第二行失败,并显示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. 这应该为我提供另一个调用的指针,但这是Activator.CreateInstance调用上的错误,接口上带有80040154。 As this is on a basic windows interface to the audio APIs I don't see why any missing components would be the issue. 因为这是在音频API的基本Windows界面上,所以我看不出为什么缺少任何组件。

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. 看来我只需要发送IntPtr作为ref参数并使用它。

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: 我已经定义了能够访问COM的C#接口:

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. 这与COM接口相对应,这也是我其他接口的设置方式。 The C++ example I am working from sends a pointer defined from the interface: 我正在使用的C ++示例发送了一个从接口定义的指针:

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#? 假设我在返回的指针中获得了正确的值,现在如何通过C#设置级别?

Thank you 谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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