Board index » cppbuilder » Complie problem with callback funtion in component

Complie problem with callback funtion in component


2006-01-06 08:49:17 AM
cppbuilder81
I'm trying to write my first component from scratch. It's to
encapsulate the MS multi media timer. At this point its written as a
class so that I can easily test it.
I expect that either at design time or run time that an the user will
provide an event function such as OnMMMTimer(TObject *Sender).
In my header file:
protected:
typedef void (__closure *OnMMMTimerEvent)(TObject *Sender);
OnMMMTimerEvent FOnMMMTimerEvent; // binds ontimer event function
void __fastcall writeMMMTimerEvent( OnMMMTimerEvent NewMMMTimerEvent )
OnMMMTimerEvent __fastcall readMMMTimerEvent(void) { return
FOnMMMTimerEvent; }
public:
__property OnMMMTimerEvent OnMMMTimer =
{read=readMMMTimerEvent, write=writeMMMTimerEvent,
default=NULL};
In my cpp file
void CALLBACK TimerEvent(UINT ID, UINT D1, DWORD Sender, DWORD D2, DWORD D3)
{ // called by the timer thread
TMMMTimer::FOnMMMTimerEvent((TObject *) Sender);
}
I get this compiler error which I don't understand:
[C++ Error] MMMTimer.cpp(53): E2231 Member TMMMTimer::FOnMMMTimerEvent
cannot be used without an object
Thanks
Nate
 
 

Re:Complie problem with callback funtion in component

"Nate Lockwood" < XXXX@XXXXX.COM >wrote in message
Quote
typedef void (__closure *OnMMMTimerEvent)(TObject *Sender);
VCL event handlers should use the __fastcall calling convention:
typedef void __fastcall (__closure *OnMMMTimerEvent)(TObject *Sender);
Incidently, the signature of your event (with __fastcall added) exactly
matches the signature of the existing TNotifyEvent event type, so you should
use that instead:
TNotifyEvent FOnMMMTimerEvent;
Quote
void __fastcall writeMMMTimerEvent( OnMMMTimerEvent NewMMMTimerEvent )
OnMMMTimerEvent __fastcall readMMMTimerEvent(void) { return
FOnMMMTimerEvent; }
You do not need those. The declaration for the event can access the member
directly:
__property TNotifyEvent OnMMMTimer = {read=FOnMMMTimerEvent,
write=FOnMMMTimerEvent};
Quote
public:
Your event needs to be declared as __published if you want the user to be
able to assign a handler at design time.
Quote
void CALLBACK TimerEvent(UINT ID, UINT D1, DWORD Sender, DWORD D2, DWORD
D3)
{ // called by the timer thread
TMMMTimer::FOnMMMTimerEvent((TObject *) Sender);
}

I get this compiler error which I don't understand:
[C++ Error] MMMTimer.cpp(53): E2231 Member TMMMTimer::FOnMMMTimerEvent
cannot be used without an object
The event is not a static member of the class. You must use a pointer to a
real object instance in order to access the event. Since you appear to be
passing the component's 'this' pointer as a user-defined value to the timer,
then you can use that ponter to reach the event, ie:
void CALLBACK TMyComponent::TimerEvent(UINT ID, UINT D1, DWORD dwUser,
DWORD dw1, DWORD dw2)
{
TMyComponent *pThis = reinterpret_cast<TMyComponent*>(dwUser);
if( pThis->FOnMMMTimerEvent )
pThis->FOnMMMTimerEvent(pThis);
}
{
//...
... = timeSetEvent(..., &TimerEvent, reinterpret_cast<DWORD>(this),
...);
//...
}
Gambit
 

Re:Complie problem with callback funtion in component

Remy Lebeau (TeamB) wrote:
Quote
>I get this compiler error which I don't understand:
>[C++ Error] MMMTimer.cpp(53): E2231 Member TMMMTimer::FOnMMMTimerEvent
>cannot be used without an object


The event is not a static member of the class. You must use a pointer to a
real object instance in order to access the event. Since you appear to be
passing the component's 'this' pointer as a user-defined value to the timer,
then you can use that ponter to reach the event, ie:

void CALLBACK TMyComponent::TimerEvent(UINT ID, UINT D1, DWORD dwUser,
DWORD dw1, DWORD dw2)
{
TMyComponent *pThis = reinterpret_cast<TMyComponent*>(dwUser);
if( pThis->FOnMMMTimerEvent )
pThis->FOnMMMTimerEvent(pThis);
}

Thanks Remy, yes I am trying to pass the compnent's 'this' pointer ...
and here is how I'm trying to do it (with the changes you suggested).
But I get a compiler error:
[C++ Error] MMMTimer.cpp(54): E2247 'TMMMTimer::FOnMMMTimerEvent' is not
accessible
TimerEvent is not declared. If I declare it:
private:
void CALLBACK TimerEvent(UINT ID, UINT D1, DWORD dwUser, DWORD D2,
DWORD D3);
//---------------------------------------------------------------------------
void __fastcall TMMMTimer::StartTimer(void)
{
DWORD dwUser = reinterpret_cast<DWORD>(this);
ID = timeSetEvent(ThisPeriod, FResolution, TimerEvent, dwUser, Mode);
}
//---------------------------------------------------------------------------
void CALLBACK TimerEvent(UINT ID, UINT D1, DWORD dwUser, DWORD D2, DWORD D3)
{
TMMMTimer *pThis = reinterpret_cast<TMMMTimer*>(dwUser);
if( pThis->FOnMMMTimerEvent ) // compiler error
pThis->FOnMMMTimerEvent(pThis); // compiler error
}
TimerEvent is not declared. If I declare it:
private:
void CALLBACK TimerEvent(UINT ID, UINT D1, DWORD dwUser, DWORD D2,
DWORD D3);
and
//---------------------------------------------------------------------------
void CALLBACK TMMMTimer::TimerEvent(UINT ID, UINT D1, DWORD dwUser,
DWORD D2, DWORD D3)
{
TMMMTimer *pThis = reinterpret_cast<TMMMTimer*>(dwUser);
if( pThis->FOnMMMTimerEvent ) // compiler error
pThis->FOnMMMTimerEvent(pThis); // compiler error
}
//---------------------------------------------------------------------------
void __fastcall TMMMTimer::StartTimer(void)
{
DWORD dwUser = reinterpret_cast<DWORD>(this); // error next line
ID = timeSetEvent(ThisPeriod, FResolution, TimerEvent, dwUser, Mode);
}
//---------------------------------------------------------------------------
Then I get complier errors:
[C++ Error] MMMTimer.cpp(68): E2034 Cannot convert 'void (__stdcall *
(_closure )(unsigned int,unsigned int,unsigned long,unsigned
long,unsigned long))(unsigned int,unsigned int,unsigned long,unsigned
long,unsigned long)' to 'void (__stdcall *)(unsigned int,unsigned
int,unsigned long,unsigned long,unsigned long)'
and
[C++ Error] MMMTimer.cpp(68): E2342 Type mismatch in parameter 'fptc'
(wanted 'void (__stdcall *)(unsigned int,unsigned int,unsigned
long,unsigned long,unsigned long)', got 'void')
Nate
 

{smallsort}

Re:Complie problem with callback funtion in component

"Nate Lockwood" < XXXX@XXXXX.COM >wrote in message
Quote
But I get a compiler error:
[C++ Error] MMMTimer.cpp(54): E2247 'TMMMTimer::FOnMMMTimerEvent'
is not accessible
The only way that can error can happen is if the callback is not a member of
the component class.
Quote
private:
void CALLBACK TimerEvent(UINT ID, UINT D1, DWORD dwUser, DWORD D2,
DWORD D3);
In order to use a class method as the callback, it has to be declared as
'static':
private:
static void CALLBACK TimerEvent(UINT uID, UINT uMsg, DWORD dwUser,
DWORD dw1, DWORD dw2);
Quote
void CALLBACK TimerEvent(UINT ID, UINT D1, DWORD dwUser, DWORD D2, DWORD
D3)
{
TMMMTimer *pThis = reinterpret_cast<TMMMTimer*>(dwUser);
if( pThis->FOnMMMTimerEvent ) // compiler error
pThis->FOnMMMTimerEvent(pThis); // compiler error
}
You need to qualify the class type in the method name:
void CALLBACK TMMMTimer::TimerEvent(UINT uID, UINT uMsg, DWORD dwUser,
DWORD dw1, DWORD dw2)
{
TMMMTimer *pThis = reinterpret_cast<TMMMTimer*>(dwUser);
if( pThis->FOnMMMTimerEvent )
pThis->FOnMMMTimerEvent(pThis);
}
Quote
[C++ Error] MMMTimer.cpp(68): E2034 Cannot convert 'void (__stdcall *
(_closure )(unsigned int,unsigned int,unsigned long,unsigned
long,unsigned long))(unsigned int,unsigned int,unsigned long,unsigned
long,unsigned long)' to 'void (__stdcall *)(unsigned int,unsigned
int,unsigned long,unsigned long,unsigned long)'
That occurs when you do not declare the class method as 'static'.
Gambit
 

Re:Complie problem with callback funtion in component

Remy Lebeau (TeamB) wrote:
Quote

That occurs when you do not declare the class method as 'static'.

Thanks, Remy, not only does it compile but my test worked.
Nate
 

Re:Complie problem with callback funtion in component

"Nate Lockwood" < XXXX@XXXXX.COM >wrote in message
Quote
Thanks, Remy, not only does it compile but my test worked.
Since multimedia timers are threaded, make sure that the code for your event
handler is thread-safe.
Gambit