tags:

views:

231

answers:

3

Hi! I'm trying to use a class member as a callback but the compiler gives me the following error:

Error 2 error C2440: 'type cast' : cannot convert from 'void (__stdcall CWaveIn::* )(HWAVEIN,UINT,DWORD_PTR,DWORD_PTR,DWORD_PTR)' to 'DWORD_PTR'

Is it possible to use a member function as a callback this way? and how do I convert the stdcall member pointer to the DWORD_PTR requested by the winapi function?

class CWaveIn
{
private:
    void CALLBACK WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
};

void CWaveIn::Open() 
{
    (...)
    MMRESULT result = ::waveInOpen(&hWaveIn, currentInputDeviceId, waveFormat, (DWORD_PTR)CWaveIn::WaveInProc, 0, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT);
}
+1  A: 

The general, though by no means perfect, solution is to make the function static.

anon
A: 

Is it possible to use a member function as a callback this way?

No. They have different signatures. A member function expects an implicit this parameter in addition to the ones listed. It can not be called as a non-member function.

and how do I convert the stdcall member pointer to the DWORD_PTR requested by the winapi function?

You can't. You'll have to write a wrapper function to use as callback instead. It should be either a static member function, or a non-member function.

jalf
ok, so the best I can do is to declade my data as global to be used by my callback?
Ruben Trancoso
More or less. A pointer to the object must be accessible from a non-member context. That might be through a global pointer or perhaps a global map containing pointers to a number of objects. Alternatively, the API might allow you to pass some user-defined data to the callback function, such as an object pointer.
jalf
+4  A: 

You cannot directly pass in class methods.

This is the right way :

class CWaveIn
{
private:
    static void CALLBACK staticWaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
    {
        CWaveIn* pThis = reinterpret_cast<CWaveIn*>( dwParam1 );
        pThis->WaveInProc( ... );
    }
    void WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
    {
       // your code
    }
};

void CWaveIn::Open() 
{
     (...)
     MMRESULT result = ::waveInOpen(&hWaveIn, currentInputDeviceId, waveFormat, CWaveIn::staticWaveInProc, this, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT);
}
Christopher
nice, but WaveInProc will be able to access member data? since its being called from a static context wont will this raise access violation?
Ruben Trancoso
waveInOpen gets passed a function pointer AND an application defined context value that gets passed back to the callback function. In this case, 'this' is passed as the context value, and in the static variant of the callback, is cast back to a CWaveIn instance, allowing the non static WaveInProc to be called.
Chris Becke