error C3867 - trying to pass member function as parameter

Started by
2 comments, last by Zahlman 14 years, 5 months ago
I have this class, in the constructor I want to start a suspended thread ( calling CreateThread(..) that receives a pointer to the function that will be the thread execution code ).. That threadfunc is a member function of this same class, VS is complaining about it, and says to me to use &class::threadfunc instead of the usually just threadfunc.. The problem is when I do it, it says theres no possible conversion between 'DWORD (__thiscall Scheduler::* )(LPVOID)' to 'LPTHREAD_START_ROUTINE' .. What can I do? The constructor:

Scheduler::Scheduler(){

	//
	uiTempoGlobal = 0;
	uiTempoNextEvent = 0;
	//-------------------

	//
	hStartSimulThread = CreateThread(NULL,0,&Scheduler::StartSimulThread,NULL,CREATE_SUSPENDED,NULL);
	//just StartSimulThread doesnt work
	//---------------------------------------------------
...

The class:


class Scheduler{

public:
	 Scheduler();
	~Scheduler();

...

...

	DWORD StartSimulThread( LPVOID lpDatap );
		HANDLE hStartSimulThread;



Advertisement
A pointer to a member function isn't the same as a pointer to a normal function. If you want to use a member function as a thread you need to use a non-member or static function as a trampoline to the member function. Something like:
DWORD trampoline(void * data) {  return (static_cast<Scheduler>(data)->StartSimulThread)();}

Note that StartSimulThread() will no longer need a void pointer argument.
Thats so confuse to me..Let me see if I get it..
You have to use a trampoline, because member function pointers are like inexistent, but I still need a member function because it mess with the actuall object(Scheduler's) data, so I just need a normal function that receives the entire object as parameter..thats it?

@.@
why the static_cast btw?




Quote:Original post by Icebone1000
because member function pointers are like inexistent


Pointers to member functions have the wrong type.

The library wants a DWORD(*)(void*).

The member function is a DWORD(Scheduler::*)(void*).

The type is different because member functions are called differently from normal functions. They need an instance of the class to be called upon. There is no way that the function pointer can say which instance to use.

Quote:so I just need a normal function that receives the entire object as parameter..thats it?

@.@
why the static_cast btw?


The library expects a DWORD(*)(void*) so that you can pass whatever data you like by making the void* point at it. (This way, it doesn't have to think about the type of the data that your function needs: it just takes your callback function and a void* pointing to your data, does the magic to make a new thread, and makes the new thread call the callback function with the data).

This gives us a clever trick that we can use to run a member function. We use the void* to point at an instance of the class, and write the callback so that it calls the member function. We need a static_cast because the callback takes in a void*, and we have to tell the compiler that it actually points at an instance of the class.

Put together, it all works like:

class Scheduler{public:	 Scheduler();	~Scheduler();......// StartSimulThread doesn't need any arguments, so we don't pass any.	DWORD StartSimulThread();	HANDLE hStartSimulThread;...Scheduler::Scheduler(){	//	uiTempoGlobal = 0;	uiTempoNextEvent = 0;	//-------------------	// We pass the pointer to the current instance ('this') as the data	// for the callback, and the trampoline as the callback.	hStartSimulThread = CreateThread(NULL,0,trampoline,this,CREATE_SUSPENDED,NULL);	//---------------------------------------------------...// This is not a member function.DWORD trampoline(LPVOID data) {	// The void* actually points at some instance of Scheduler, as above.	// So here we make the cast, and call the member function. I'll show	// it in 2 lines; is it clearer now?	Scheduler* scheduler = static_cast<Scheduler*>(data);	return scheduler->StartSimulThread();}

This topic is closed to new replies.

Advertisement