Can I use CALLBACK functions in class ?

Started by
10 comments, last by 3ddreams 18 years, 4 months ago
I have a class like below. When I define EnumJoysticksCallback function out from class everythins is ok but When I define EnumJoysticksCallback function in class "g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,EnumJoysticksCallback,NULL, DIEDFL_ATTACHEDONLY )" function not accept this function and I am getting this error "...error C2664: 'IDirectInput8A::EnumDevices' : cannot convert parameter 2 from 'BOOL (const DIDEVICEINSTANCE *,void *)' to 'LPDIENUMDEVICESCALLBACKA'" I am trying to insert callback function in class. Can I use callback functions as a class member? Is this possible? Thanks.


class CBT_INPUT
{
private:
	HINSTANCE  g_hinst;
	HRESULT         hr; 
	LPDIRECTINPUT8       g_pDI;
	LPDIRECTINPUTDEVICE8 g_pKeyboard,g_pMouse,g_pJoystick;	
public:
	...
        HRESULT InitInput(HWND hWnd,bool bExclusive,bool bForeground,bool bWinkeys);
	BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* 
pdidInstance, VOID* pContext );
        ...

}

////////////////////////////////////////////////////////////////////

HRESULT CBT_INPUT::InitInput(HWND hWnd,bool bExclusive,bool bForeground,bool bWinkeys){
        ...
	if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,EnumJoysticksCallback,NULL, DIEDFL_ATTACHEDONLY ) ) ){
		return hr;
	}
        ...
}




[Edited by - 3ddreams on November 21, 2005 12:24:00 PM]
Advertisement
Non static member functions cannot be used as callbacks for EnumDevices().
You can C++Builder compiler that supports pointers to members. But that requires special knowledge
ai-blog.org: AI is discussed here.
*bUrp*
As replied you can't do exactly what you are trying to do. I notice you are using DX. If you look at the samples (IIRC, it's in the common directory that all the samples refer to for their window class) you can see how MS worked around the problem.
I solved problem by using static. Thanks SiCrane and another frends. But I have an anoter problem. When I declare g_pDI and g_pJoystick out from class program working. When declarated in class I am getting this error from in EnumJoysticksCallback :

.. error C2227: left of '->CreateDevice' must point to class/struct/union
.. error C2597: illegal reference to non-static member 'CBT_INPUT::g_pJoystick'

I looked C2597 error from MSDN. It says To access the nonstatic member, you must create an instance of the class and use a member-access operator (. or ->). If I do this g_pDI and g_pJoystick variables doesn't initialize and program will generete error.

CBT_INPUT test; //No compile error but program generate error and terminate
test.g_pDI->CreateDevice( pdidInstance->guidInstance, &test.g_pJoystick, NULL );

If I can't declare g_pDI and g_pJoystick variables in class I can't declare multi objects because every object will use same variables(g_pDI,g_pJoystick). I can't get out from this job. I need HELP. My c++ and english knowledge not enough.


	//BTInput.h  BEGINclass CBT_INPUT{private:	HINSTANCE  g_hinst;	HRESULT         hr;        LPDIRECTINPUT8       g_pDI;		LPDIRECTINPUTDEVICE8 g_pKeyboard,                             g_pMouse,                             g_pJoystick;			static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext );	static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext );...}// BTInput.h END//BTnput.cpp BEGINBOOL CALLBACK CBT_INPUT::EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,VOID* pContext ){	  HRESULT hr;        //ERROR C2227,C2597      ->  hr = g_pDI->CreateDevice( pdidInstance->guidInstance, &g_pJoystick, NULL );	  if( FAILED(hr) )  return DIENUM_CONTINUE;	return DIENUM_STOP;}.....//BTnput.cpp END
Quote:Original post by eastcoastsurfer
As replied you can't do exactly what you are trying to do. I notice you are using DX. If you look at the samples (IIRC, it's in the common directory that all the samples refer to for their window class) you can see how MS worked around the problem.


I am trying to write an input class. It done. But some variables generate errors when I use their in class. If I solve this problem input class comletely will done. In SDK samples callback functions not declarated in class but I tryed to use their in class. At this moment callback problem solved but variable problem continue. I wrote this problem above before this post.
Okay, the important part: there is a HUGE difference between regular member functions and static functions. Hence there are two totally different kinds of function pointers and as the callbacks require global or static functions you won't have a this pointer and can't access anything but other static data (let's call them pseudo global).

So, unless you can either make the data your callback requires static as well or find a way to forward the changes you are pretty much stuck.

One rather ugly way comes to mind. Add a static pointer to an instance to your class. There shouldn't be much point in having more than one actual object reacting to input, even though it would be possible this way.

ie. something like this
class C {  static C* instance;  static void callback() {    if (!instance) return;    instance->bla;    instance->whatever=something;  }    void bla() {}  int whatever;};C* C::instance=0;


Now obviously whenever you create the object that should handle the input you need to do either
instance=this;
in it's constructor (doesn't sound to useful), in some kind of setAsInstance() function or just do
C object;
C::instance=&object
f@dzhttp://festini.device-zero.de
My problem shortly same as following.

struct VERTEX{	float x,y,z;};typedef VERTEX *LPVERTEX;class FOO{public:	static void Test();	LPVERTEX a;};void FOO::Test(){		a->x=100.0f;      //error C2227: left of '->x' must point to class/struct/union	printf("%f",a->x);//error C2227:..}int _tmain(int argc, _TCHAR* argv[]){	FOO fo;	fo.Test();	return 0;}
Hi,

this is an elegant solution i use; it works for me - and a lot of people
It looks confusing, but its really simple.


Firstly, you create the static member function to use in the call back, as you have done :)
You only need to specify the callback as static... nothing else.


Second, set the callback function from within your class, and pass it the static EnumJoysticksCallback function (as i assume you have done already).
AND, where you have NULL, pass the class pointer (this)!

e.g.
// Note the 'this' pointer, casted to void*g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,EnumJoysticksCallback,(void*)this,DIEDFL_ATTACHEDONLY )"


Third, now from within your static callback function, you can access the class member variables through the the class pointer; this is how you get around the inability to access non-static member functions and variables.

eg:

static whatever CBT_INPUT::EnumJoysticksCallback(const DIDEVICEINSTANCE*    pdidInstance, VOID* pContext){     // pContext is (or should be) the 'this' parameter you passed in     // to the EnumDevices, it is of type 'void' and needs to be cast to     // a CBT_INPUT pointer     CBT_INPUT* ptr = (CBT_INPUT*)pContext;      //     // Now, Access you member functions like this, it works for private     // members as well!     //     ptr->g_hinst;     ptr->g_pDI;    // etc etc}


you will notice alot of APIs that allow you to specify a callback function, will have a void* parameter.... this is what its mostly used for (im my experience)

Hope it works :)
Paul


This topic is closed to new replies.

Advertisement