Re: Using a callback function name as an argument in a function



Overall, I agree. I haven't written a "callback" method since I started using C++;
virtual methods are the best approach. If you need a callback in C++, you are probably
making fundamental design errors.

The API callbacks are truly quaint, and the worst of them don't allow passing an arbitrary
user parameter (and it shows the defective thinking that in 20 years of the API, nobody
has replaced these with an Ex version that solved this long-standing problem). They
should not be used as models of programming methodology.

As pointed out, the error message is screamingly obvious:

error C2664: 'lineInitializeExA' : cannot convert parameter 3 from 'void
(unsigned long,unsigned long,unsigned long,unsigned long,unsigned
long,unsigned long)' to 'void (__stdcall *)(unsigned long,unsigned
long,unsigned long,unsigned long,unsigned long,unsigned long)'
None of the functions with this name in scope match the target type

Look at what it says:

cannot convert from
void void
(__stdcall *)
(unsigned long, (unsigned long,
unsigned long, unsigned long,
unsigned long, to unsigned long,
unsigned long, unsigned long,
unsigned long, unsigned long,
unsigned long) unsigned long)

Is the difference not obvious? It WANTs a prototype that has __stdcall, and you gave it a
method which was NOT __stdcall!

Since it is a callback function, you should have supplied a CALLBACK (that is, __stdcall)
method in your function definition

But you should abandon the concept of callback as a way of life.
joe

On Thu, 17 Jan 2008 12:25:43 +0100, "Giovanni Dicanio" <giovanni.dicanio@xxxxxxxxxxx>
wrote:

To add to what others correctly wrote, have you considered the option of
changing your design, making it more C++ and less C?
What IMHO could be good is to define an *interface* (C++), which a "worker"
object must implement, instead of C-style callbacks.

e.g.

// Instead of having a call-back, use a C++ interface
class ILineProcessor
{
public:
virtual ~ILineProcessor(); // virtual dtor for proper cleanup

// The job that the callback did in the previous design
virtual void DoWork( ...parameters... ) = 0;

// ... other interface methods, if needed...
};

Then you derive a concrete class which implements the above interface, and
this concrete class does the real job.
Having defined a class (and not just a C-function callback), you can store
lots of useful information, like additional status information (via private
data members), etc. The resulting code will be more robust, extensible, just
more quality.

I think that the call-backs are an old design, considering that the Win32
API is a kind of "C" framework. So, in C, call-backs are useful. But IMHO in
C++ we can use *interfaces* to get better quality code.
In fact, there are also some new APIs in Vista (about common dialogs, IIRC),
that works with COM *interfaces* (because the concept of interfaces is more
robust and more quality than C-style call-backs).

Just my 2 cents.

Giovanni



"Dan Gistenson" <d.gistenson@xxxxxxxxxxxxx> ha scritto nel messaggio
news:WDbjj.51$Rg1.38@xxxxxxxxxxxxxxxxxxxxxxx
Hi.

Can someone tell me where I'm going wrong with this problem in my vc6 mfc
sdi project, and tell me how to fix it? I understand the general meaning
of
the compiler's 2664 error message, but I don't understand what's wrong
with
my approach and how to fix it. The problem lies with argument 3 of
lineInitializeEx() and/or the prototype and definition of
lineCallbackFunc().

I used Class wizard to add the member function lineCallbackFunc() to my
doc
class. The function will be used as a callback function, by using it as
the
third argument in a call to lineInitializeEx() which I hav placed in the
OnNewDocument member function of my doc class.

The compiler error message, the prototype and definition of the callback
function, and the call to lineInitializeEx() are below, in that order.
What
am I doing wrong, and how do I fix it?

The compiler error message is:
error C2664: 'lineInitializeExA' : cannot convert parameter 3 from 'void
(unsigned long,unsigned long,unsigned long,unsigned long,unsigned
long,unsigned long)' to 'void (__stdcall *)(unsigned long,unsigned
long,unsigned long,unsigned long,unsigned long,unsigned long)'
None of the functions with this name in scope match the target type

The callback function's prototype is:
void lineCallbackFunc(DWORD hDevice, DWORD dwMsg, DWORD
dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);

The callback function's definition is:
void CFoneIODoc::lineCallbackFunc (DWORD hDevice, DWORD dwMsg, DWORD
dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
// My code will go here.
}

Finally, the call to lineInitializeEx() is: (Argument 3 is the issue.)
lResult = lineInitializeEx( &hLineApp, NULL, lineCallbackFunc, "TAPI
App!",
&dwNumDevs, &dwHighApiVersion, &lineInit );

Please help.
Thanks,
Dan



Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.



Relevant Pages

  • BUG: timeSetEvent() wraps after inteval of 429496
    ... There is a bug in timeSetEvent, which is used to schedule a callback ... milliseconds the actual time period will wrap back to x-429496. ... The actual exports for these time functions are in winmm.dll, and this bug ... void CALLBACK TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD ...
    (microsoft.public.win32.programmer.mmedia)
  • Re: timeSetEvent() wraps after inteval of 429496
    ... setting a period of 430000 which generate a callback in 504ms. ... > The actual exports for these time functions are in winmm.dll, and this bug ... > // This code reproduces a bug in timeSetEvent() where if a periodic timing ... > void CALLBACK TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, ...
    (microsoft.public.win32.programmer.mmedia)
  • Re: Using a callback function name as an argument in a function
    ... changing your design, making it more C++ and less C? ... Having defined a class (and not just a C-function callback), ... void lineCallbackFunc(DWORD hDevice, DWORD dwMsg, DWORD ... DWORD dwParam1, DWORD dwParam2, DWORD dwParam3); ...
    (microsoft.public.vc.mfc)
  • Re: Pointers... again... f-n noobs...
    ... > void CALLBACK TestProc(UINT, UINT, DWORD, DWORD, DWORD); ... > void CALLBACK TestProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Visual Basic 6.0 + WMM API not stable on P4 with HyperThreading
    ... the secondary CPU using the SetProcessAffinity API. ... my callback function uses SetTimer with the hWnd of the ... > Public Sub CallBack(ByVal hDev As Long, ByVal uMsg As Long, ByVal ... > code so that it uses CriticalSections around access to globals? ...
    (microsoft.public.vb.bugs)