【问题标题】:Why is QueryInterface() returning E_INVALIDARG?为什么 QueryInterface() 返回 E_INVALIDARG?
【发布时间】:2021-03-15 00:34:58
【问题描述】:

我在编写一个项目时遇到了一个错误,QueryInterface() 正在返回 E_INVALIDARG,我不知道哪个参数无效,因为两个参数都很简单,是我忽略了一些简单的东西还是什么?

失败的部分来自微软自己,特别是 documentation,如果我做错了什么,请告诉我

HRESULT CreateSecondaryBuffer(LPDIRECTSOUND8 lpDirectSound, LPDIRECTSOUNDBUFFER8* ppDsb8, LPCWSTR lpName) {
    WAVEFORMATEX wfx;
    DSBUFFERDESC dsbdesc;
    LPDIRECTSOUNDBUFFER pDsb = NULL;
    HRESULT hr = 0;

    void* lpRes;
    HRSRC hResInfo;
    HGLOBAL hRes;

    LPVOID lpvWrite;
    DWORD  dwLength;

    waveFile myWave;
    memset(&myWave, 0, sizeof(waveFile));
    // Find the WAVE resource. 

    hResInfo = FindResource(wc.hInstance, lpName, L"WAVE");
    if (hResInfo == NULL)
        return FALSE;

    // Load the WAVE resource. 

    hRes = LoadResource(wc.hInstance, hResInfo);
    if (hRes == NULL)
        return FALSE;

    // Lock the WAVE resource and play it. 

    lpRes = LockResource(hRes);
    char* wavMem = static_cast<char*>(lpRes);
    memcpy(&myWave, wavMem, 36);
    wavMem += 36;
    

    while (myWave.Subchunk2ID[0] != 'd' && myWave.Subchunk2ID[1] != 'a' && myWave.Subchunk2ID[2] != 't' && myWave.Subchunk2ID[3] != 'a') {
        memcpy(&myWave.Subchunk2ID, wavMem, 8);
        if (myWave.Subchunk2ID[0] != 'd' && myWave.Subchunk2ID[1] != 'a' && myWave.Subchunk2ID[2] != 't' && myWave.Subchunk2ID[3] != 'a') {
            wavMem += myWave.Subchunk2Size;
            wavMem += 8;
        }
    }
    wavMem += 8;

    char* soundData = new char[myWave.Subchunk2Size];
    memcpy(soundData, wavMem, myWave.Subchunk2Size);
    FreeResource(hRes);

    // Set up WAV format structure. 

    memset(&wfx, 0, sizeof(WAVEFORMATEX));
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = myWave.NumChannels;
    wfx.nSamplesPerSec = myWave.SampleRate;
    wfx.nBlockAlign = myWave.BlockAlign;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
    wfx.wBitsPerSample = myWave.BitsPerSample;

    // Set up DSBUFFERDESC structure. 

    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags =
         DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;
    dsbdesc.dwBufferBytes = myWave.Subchunk2Size;
    dsbdesc.lpwfxFormat = &wfx;

    hr = lpDirectSound->CreateSoundBuffer(&dsbdesc, &pDsb, NULL);
    if (SUCCEEDED(hr))
    {
        if (DS_OK == pDsb->Lock(
            0,          // Offset at which to start lock.
            0,          // Size of lock; ignored because of flag.
            &lpvWrite,  // Gets address of first part of lock.
            &dwLength,  // Gets size of first part of lock.
            NULL,       // Address of wraparound not needed. 
            NULL,       // Size of wraparound not needed.
            DSBLOCK_ENTIREBUFFER))  // Flag.
        {
            memcpy(lpvWrite, soundData, dwLength);
            pDsb->Unlock(
                lpvWrite,   // Address of lock start.
                dwLength,   // Size of lock.
                NULL,       // No wraparound portion.
                0);         // No wraparound size.
        }
        hr = pDsb->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)ppDsb8);
        pDsb->Release();
    }

    delete[] soundData;
    return hr;
}

【问题讨论】:

  • LPDIRECTSOUND8 lpDevice; LPDIRECTSOUNDBUFFER8* pMainSecondaryBuffer; CreateSecondaryBuffer(lpDevice, pMainSecondaryBuffer, L"mainSong");
  • 当我尝试发送 &amp;pMainSecondaryBuffer 时,编译器不喜欢它并且不会编译
  • 那是因为你错误地声明了pMainSecondaryBuffer。您的间接层级过多。
  • 现在真的没有理由使用 DirectSound,除非您的目标是 Windows XP。看看WASPI,如果你只是和/或XAudio2
  • DirectSound 不像 Windows 98/ME 时代那样“低级”。从 Windows Vista 开始,系统上的所有音频都通过 WASAPI 进行最终输出。DirectSound 和 XAudio2 都是通过 WASAPI 发送输出的软件混音器,但 XAudio2 的设计更加现代,避免了大量数据复制。

标签: c++ winapi com directsound


【解决方案1】:

QueryInterface() 只有 2 个参数可供 E_INVALIDARG 抱怨,而且在您的 CreateSecondaryBuffer() 函数内部对我来说它们看起来很好。第一个参数被传递一个硬编码的 IID,所以问题必须出在第二个参数上,它期望被传递一个指向(在这种情况下)IDirectSoundBuffer8* 变量的指针,QueryInterface() 可以写入内存地址一个DirectSoundBuffer8 对象。因此,您的 CreateSecondaryBuffer() 函数的 ppDsb8 参数很可能没有像您期望的那样被传递给 IDirectSoundBuffer8* 变量的有效指针。

更新:在看到您添加的评论后,您确实传递了一个无效指针到CreateSecondaryBuffer()ppDsb8 参数。调用者的pMainSecondaryBuffer 指针声明不正确,并且在传递给CreateSecondaryBuffer()未初始化,因此您将错误的指针传递给QueryInterface(),因此出现E_INVALIDARG 错误。

改用这个:

LPDIRECTSOUND8 lpDevice = ...; // <-- make sure it points to a valid device object...
LPDIRECTSOUNDBUFFER8 pMainSecondaryBuffer;
CreateSecondaryBuffer(lpDevice, &pMainSecondaryBuffer, L"mainSong");

【讨论】:

  • lpDevicepMainSecondaryBuffer 是 2 种不同类型的对象,不会像您所说的那样工作,lpDevice 是一个 device 对象,用于创建一个新的 buffer对象,编译器不喜欢LPDIRECTSOUNDBUFFER8* pMainSecondaryBuffer = &amp;lpDevice;,也不喜欢CreateSecondaryBuffer(lpDevice, &amp;lpDevice, L"mainSong");,如果我将LPDIRECTSOUNDBUFFER8* pMainSecondaryBuffer初始化为NULL,它仍然不起作用
  • "lpDevicepMainSecondaryBuffer 是 2 种不同类型的对象,不会像您所说的那样工作," - 我刚刚意识到这一点。我已经在我的回答中修复了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
相关资源
最近更新 更多