Reputation: 10931
I'm new with call-back function. I wrote a Timer
class. It stores callback functions in it and calls them back after their respective periods.
Timer.h
#ifndef UTILITY_CLASSES__TIMER_H
#define UTILITY_CLASSES__TIMER_H
#include <stdint.h>
#include <list>
#include <Windows.h>
class Timer
{
public:
static uint64_t LAST_TIMER_ID;
uint64_t TimerId;
uint64_t KillId;
typedef void (*TimerCallBackFunction) (DWORD, uint64_t);
Timer(UINT Period, TimerCallBackFunction CbFunction);
~Timer();
protected:
class TimerInfo
{
public:
TimerInfo(TimerCallBackFunction Cbf, uint64_t Tid, uint64_t Kid)
: Callback(Cbf), TimerId(Tid), KillId(Kid) {}
TimerCallBackFunction Callback;
uint64_t TimerId;
uint64_t KillId;
};
static VOID CALLBACK TimerProc( _In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime);
static std::list<TimerInfo> Timers;
};
#endif // UTILITY_CLASSES__TIMER_H
Timer.cpp
#include "Timer.h"
#include <Windows.h>
uint64_t Timer::LAST_TIMER_ID = 0;
Timer::Timer(UINT Period, TimerCallBackFunction CbFunction)
{
TimerId = ++LAST_TIMER_ID;
KillId = SetTimer(NULL, TimerId, Period, Timer::TimerProc);
if (KillId == NULL)
{
LAST_TIMER_ID--; // roll back
TimerId = 0;
}
else
{
Timers.push_back(TimerInfo(CbFunction, TimerId, KillId));
}
}
Timer::~Timer()
{
for (std::list<TimerInfo>::const_iterator it=Timers.begin(); it!=Timers.end(); ++it)
{
if (it->TimerId == TimerId)
{
Timers.erase(it);
break;
}
}
}
VOID CALLBACK Timer::TimerProc( _In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime)
{
for (std::list<TimerInfo>::const_iterator it=Timers.begin(); it!=Timers.end(); ++it)
{
if (it->TimerId == idEvent)
{
it->Callback(dwTime, it->TimerId);
break;
}
}
}
main.cpp
#include <Windows.h>
#include "Timer.h"
class MyClass
{
public:
void CallMe(DWORD Time, uint64_t TimerId)
{
MessageBoxW(NULL, L"Callback function is called!",
L"Notification", MB_ICONINFORMATION);
}
};
int APIENTRY wWinMain( _In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
// ...
MyClass MyObject;
Timer TimerObject(10000, MyObject.CallMe); // Line 114
//...
return 0;
}
I get this error message when I compile this code:
Line 114
error C3867:
'MyClass::CallMe': function call missing argument list; use '&MyClass::CallMe' to create a pointer to member
I can't get my code run when I change MyObject.CallMe
to &MyClass::CallMe
or &MyObject.CallMe
at line 114.
What am I doing wrong in my code?
IDE: Microsoft Visual Studio 2012
Documentations: SetTimer, TimerProc
Upvotes: 0
Views: 714
Reputation: 55395
typedef void (*TimerCallBackFunction) (DWORD, uint64_t);
declares a typedef for a pointer to free function and these can't be used to point to member functions. You need a pointer to member function:
typedef void (MyClass::*TimerCallBackFunction) (DWORD, uint64_t);
You'll need to forward declare MyClass
before you make that typedef and also do what the error message says:
Timer TimerObject(10000, &MyObject::CallMe);
// ^^^^^^^^^^^^^^^^^
Recommended reading: Pointers to member functions section on C++ FAQ Lite.
Upvotes: 2
Reputation: 3344
I would do with using std::function
rather than a function pointer, and then use std::bind
with placeholders:
Change the typedef to
typedef std::function<void (DWORD, uint64_t)> TimerCallBackFunction;
and in WinMain()
, bind a std::function
to CallMe()
of the instance MyObject
, which will then be called with the two parameters replacing the placeholders.
MyClass MyObject;
Timer TimerObject(10000, std::bind(&MyClass::CallMe,
MyObject,
std::placeholders::_1,
std::placeholders::_2));
Upvotes: 1