为什么 QueryInterface() 返回 E_INVALIDARG?
Why is QueryInterface() returning E_INVALIDARG?
我正在编写一个项目,我遇到了一个错误,其中 QueryInterface()
返回 E_INVALIDARG
,我不知道哪个参数无效,因为两个参数都足够简单,我是不是忽略了什么简单还是什么?
失败的部分来自 Microsoft 本身 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;
}
QueryInterface()
的 E_INVALIDARG
只有 2 个参数值得抱怨,在我看来,它们在你的 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");
我正在编写一个项目,我遇到了一个错误,其中 QueryInterface()
返回 E_INVALIDARG
,我不知道哪个参数无效,因为两个参数都足够简单,我是不是忽略了什么简单还是什么?
失败的部分来自 Microsoft 本身 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;
}
QueryInterface()
的 E_INVALIDARG
只有 2 个参数值得抱怨,在我看来,它们在你的 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");