waveout — преобразование функции обратного вызова в DWORD_PTR при переполнении стека

На самом деле новичок в C ++.
Я написал этот код, но говорит, что не может конвертировать из «waveOutProc» в «DWORD_PTR». Не могли бы вы сказать мне, как это исправить?

Спасибо

void CALLBACK Audio::waveOutProc(HWAVEOUT hWaveOut, unsigned int uMsg,
unsigned long dwInstance, unsigned long dwParam1,
unsigned long dwParam2)
{
/*
* pointer to free block counter
*/
int* freeBlockCounter = (int*)dwInstance;
/*
* ignore calls that occur due to openining and closing the
* device.
*/
if(uMsg != WOM_DONE) { return ; }
EnterCriticalSection(&waveCriticalSection) ;
(*freeBlockCounter)++ ;
LeaveCriticalSection(&waveCriticalSection) ;
}

////////////////////////////////////////////////// ////////////////////////////////

void Audio::playSound(const char* filename)
{
HWAVEOUT hWaveOut ;
HANDLE hFile;
WAVEFORMATEX wfx ;
char buffer[1024];
int i;

...

if(waveOutOpen(
&hWaveOut,
WAVE_MAPPER,
&wfx,
(DWORD_PTR)waveOutProc,            ///////////Error Point
(DWORD_PTR)&waveFreeBlockCount,
CALLBACK_FUNCTION
) != MMSYSERR_NOERROR) {
fprintf(stderr, "unable to open wave mapper device\n");
ExitProcess(1);
}

...
}

2

Решение

Преобразование указателей функций в указатели данных является неопределенным поведением, поэтому вам не следует делать это в первую очередь. (Я понимаю, что функция Win API ожидает этого).

Также Вы не можете передавать функции-члены как обратные вызовы в C / C ++, если не обрабатываете неявные this аргумент.

Ваш целевой обратный вызов имеет следующую подпись

void CALLBACK waveOutProc(
HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2
);

В то время как Audio :: waveOutProc, вероятно, является функцией-членом, которая подразумевает этот аргумент.

void CALLBACK waveOutProc(Audio*,
HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2
);

Просто определите waveOutProc вместо статической или свободной функции.

5

Другие решения

waveOutProc — это функция, поэтому вы не можете привести ее к целочисленному типу (значению). Кроме того, я думаю, что waveOutProc также не является статическим членом вашего класса? Вы можете передавать статические функции только как функции обратного вызова.

0

Ошибка, которую вы опубликовали в ваших комментариях, указывает на то, что waveOutProc является функцией-членом Audio Класс и C ++ не позволят вам назначить функцию-член параметру или переменной, которая ожидает «нормальную» функцию. Это потому, что функции-члены имеют неявный параметр, называемый this который является указателем на Audio экземпляр класса.

Вместо этого считается хорошей практикой написание так называемой статической функции-члена ( static Ключевое слово означает, что не существует неявного this параметр), который оборачивает функцию-член, которую вы хотите вызвать. Это возможно, потому что waveOutOpen принимает переменную пользовательских данных в качестве 5-го параметра, который затем передается статическому обратному вызову. Оболочка статической функции-члена лучше, чем просто сделать статический обратный вызов, потому что вы можете получить доступ все ваших переменных-членов классов (а не только одна переменная, например, freeBlockCounter в твоем случае). Ваша статическая оболочка функции-члена может выглядеть так:

class Audio {
private:
int freeBlockCounter;
public:
....
static void CALLBACK waveOutProcWrapper(HWAVEOUT hWaveOut, unsigned int uMsg,
unsigned long dwInstance,
unsigned long dwParam1,
unsigned long dwParam2);
void waveOutProc(HWAVEOUT hWaveOut, unsigned int uMsg, unsigned long dwParam1,
unsigned long dwParam2);
};

и реализация wrapperProc:

void CALLBACK Audio::waveOutProcWrapper(HWAVEOUT hWaveOut, unsigned int uMsg,
unsigned long dwInstance,
unsigned long dwParam1,
unsigned long dwParam2) {
((Audio*)dwInstance)->waveOutProc(hWaveOut, uMsg, dwParam1, dwParam2);
}

Обратите внимание, как dwInstance параметр «конвертируется» в неявный this параметр. Теперь вы можете поставить waveOutProcWrapper в waveOutOpen следующим образом:

if(waveOutOpen(
&hWaveOut,
WAVE_MAPPER,
&wfx,
(DWORD_PTR)waveOutProcWrapper,            ///////////Error Point
(DWORD_PTR)this,
CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
fprintf(stderr, "unable to open wave mapper device\n");
ExitProcess(1);
}
0
По вопросам рекламы [email protected]