Конвертировать функцию обратного вызова в DWORD_PTR в C++

На самом деле новичок в 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);
}

...
}

3 ответа

Решение

Преобразование указателей функций в указатели данных является неопределенным поведением, поэтому вам не следует делать это в первую очередь. (Я понимаю, что функция 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 вместо статической или свободной функции.

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

Ошибка, которую вы опубликовали в ваших комментариях, указывает на то, что 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);
}  
Другие вопросы по тегам