如何使用 WRL ComPtr 初始化 WinRT AudioGraphSettings?

How to initialize WinRT AudioGraphSettings using WRL ComPtr?

使用 C++/WinRT,AudioGraphSettings 可以使用其构造函数轻松初始化:

AudioGraphSettings settings(AudioRenderCategory::Media);

我无法在我的 WRL 项目中使用它。下面是我的实现

ComPtr<IAudioGraphSettings> settings;
Windows::Foundation::GetActivationFactory(
    HStringReference(RuntimeClass_Windows_Media_Audio_AudioGraphSettings).Get(),
    &settings
);

settings 仍然为 null,我不知道如何使用所需的 AudioRenderCategory 构造函数对其进行初始化。

如果我像下面那样做,我会遇到访问冲突崩溃,因为它仍然是空的。

settings->put_AudioRenderCategory(AudioRenderCategory::AudioRenderCategory_Media);

ABI 级别的类型激活比在 C++ 中实例化类型等更复杂。公认的简洁 documentation 概述了不同的机制:

WinRT defines three activation mechanisms: direct activation (with no constructor parameters), factory activation (with one or more constructor parameters), and composition activation.

IAudioGraphSettings 类型属于第二类:它根据 AudioRenderCategory 类型的单个参数实例化一个类型。因此实例化类型是一个 two-phase 过程:

  1. 检索激活工厂
  2. 使用激活工厂实例化一个类型

问题中的代码将两个操作混为一谈,调用 GetActivationFactory returns 一个 HRESULT 值 0x80004002,即 E_NOINTERFACE。它需要改为请求 IAudioGraphSettingsFactory 接口,然后使用该工厂实例化 IAudioGraphSettings 类型。

以下是一个完整的实现,说明了如何激活 IAudioGraphSettings 类型:

#include <wrl/wrappers/corewrappers.h>
#include <wrl/client.h>

#include <windows.foundation.h>
#include <windows.media.audio.h>
#include <windows.media.render.h>

#pragma comment(lib, "windowsapp")

using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Media::Audio;
using namespace ABI::Windows::Media::Render;

int main()
{
    RoInitializeWrapper init { RO_INIT_MULTITHREADED };
    HRESULT hr { init };
    if (FAILED(hr))
        return hr;

    // Retrieve activation factory
     ComPtr<IAudioGraphSettingsFactory> settings_factory {};
     hr = GetActivationFactory(
         HStringReference(RuntimeClass_Windows_Media_Audio_AudioGraphSettings).Get(),
         &settings_factory);
     if (FAILED(hr))
         return hr;

     // Use activation factory to instantiate type
     ComPtr<IAudioGraphSettings> settings {};
     hr = settings_factory->Create(AudioRenderCategory_Media, &settings);
     if (FAILED(hr))
         return hr;

    return hr;
}

这就是 ABI 级别的情况,ABI 级别最终是 WRL 所在的位置。 C++/WinRT 处理所有样板代码,并将参数化工厂激活巧妙地映射到 C++ 构造函数实现上。这就是 C++/WinRT 实现如此紧凑的原因。