Help! VC++ 6.0 wont allow type cast from function ptr to DWORD

I am trying to play wave audio data blocks with the low-level functions provided by Windows and declared in <mmsystem.h>. My problem is I can't get the compiler to allow the type cast from the Wave callback function pointer to DWORD, which the waveOutOpen() function expects for parameter 4. I have tried several ways, all without success:

Res = waveOutOpen( &WaveDevice, AudioDevice, &Wfmt, (DWORD)WaveCallback, 0UL, CALLBACK_FUNCTION);

Res = waveOutOpen( &WaveDevice, AudioDevice, &Wfmt, reinterpret_cast<DWORD>(WaveCallback), 0UL, CALLBACK_FUNCTION);

Res = waveOutOpen( &WaveDevice, AudioDevice, &Wfmt, static_cast<DWORD>(WaveCallback), 0UL, CALLBACK_FUNCTION);

I have also tried casting to int, unsigned int, and (void *) with no success.

The MSDN documentation says I should be able to cast from any pointer type to any integral type using reinterpret_cast, but it doesn't work. Is this a bug? Is there a workaround? Here is the error message the compiler gives:

------------
D:\TOM\Code\DAWin\DAWinDlg.cpp(356) : error C2440: 'reinterpret_cast' : cannot convert from 'void (__stdcall CDAWinDlg::*)(struct HWAVEOUT__ *,unsigned int,unsigned long,unsigned long,unsigned long)' to 'unsigned long'.
Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast.
------------

The message is similar regardless of how I try to do the type cast. What is a function-style cast?
[1591 byte] By [tbchambe] at [2007-11-18 0:34:13]
# 1 Re: Help! VC++ 6.0 wont allow type cast from function ptr to DWORD
I'll bet you are tring to use a non-static MEMBER FUNCTION. This is a totally different animal than a regular function as it needs both the address of the code and the "this" pointer. This information can not be packed into a DWORD.

Solution #1, use either a static member function or a global function...
TheCPUWizard at 2007-11-9 13:02:30 >
# 2 Re: Help! VC++ 6.0 wont allow type cast from function ptr to DWORD
To add some more information on the problem that TheCPUWizard already correctly mentioned...

The problem is that every thread/callback function has its own prototype, which determines the parameters that gets passed from the operating system to it.

In C++ every member function has a hidden parameter - the so-called 'this' pointer which will be automatically passed to the function. C++ is able to associate a function with a particular instance of an object by means of the 'this' pointer. Member functions access member variables through the 'this' pointer...

class CFoo
{
public:
void Function()
{
m_iInteger = 0;
}

private:
int m_iInteger;
};

If you compile this code it will be compiled as

class CFoo
{
public:
void Function(CFoo *this)
{
this->m_iInteger = 0;
}

private:
int m_iInteger;
};

The operating system does not call thread/callback functions through objects therefore it cannot handle the automatically added 'this' pointer... To get a member functions working as a thread/callback routine you need to tell the compiler explicitly not to expect a 'this' pointer. To avoid the automatic 'this' pointer you have two possibilities:

- Non-member functions
- Static member functions

Non-member functions are not part of a class and therefore do not have a 'this' pointer. Static member functions do not receive a 'this' pointer either...

Therefore if you want to use a member function as a thread/callback routine you need to declare it as 'static'...

For more information you might take a look at:

http://support.microsoft.com/default.aspx?scid=KB;EN-US;q102352&
http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnarvc/html/msdn_callb.asp
Andreas Masur at 2007-11-9 13:03:32 >
# 3 Re: Help! VC++ 6.0 wont allow type cast from function ptr to DWORD
Thanks for your help. Everything is obvious in retrospect.

However, the options you suggested were too messy, since all of my other wave-playing code was in dialog member functions I couldnt call them from the non-member callback function, and if I declared the callback function as a friend, the dialog object was out of scope when I needed to call the member functions, and when I moved the dialog object to global scope, the MFC framework choked on that...

SO...

I changed the callback mode to CALLBACK_WINDOW rather than CALLBACK_FUNCTION and re-declared the callback function as a message handler for the MM_WOM_DONE message. This works a lot better.
tbchambe at 2007-11-9 13:04:30 >
# 4 Re: Help! VC++ 6.0 wont allow type cast from function ptr to DWORD
Originally posted by tbchambe
Thanks for your help. Everything is obvious in retrospect.

However, the options you suggested were too messy, since all of my other wave-playing code was in dialog member functions I couldnt call them from the non-member callback function, and if I declared the callback function as a friend, the dialog object was out of scope when I needed to call the member functions, and when I moved the dialog object to global scope, the MFC framework choked on that...

You could have passed the actual object pointer ('this') through the fifth argument of 'waveOutOpen()'...

Nevertheless...as long as everything is working fine as expected you do not need to worry... :cool:
Andreas Masur at 2007-11-9 13:05:32 >