Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

To pass a pointer to a member function

I have an class with instance functions (or methods?). From within an instance, I try to pass pointers to those functions to a library. The library expects static functions.

When I pass my pointers to the callback functions, the compiler complains that my functions are not static. I tried to put make them static, but if I do so, then I can't access the instance fields from within the functions.

How could I go around this?

Similar question is : Using a C++ class member function as a C callback function where they suggest to put the method static. However I can't do that, or I don't see how I could.

Code

GlutController::GlutController (int argc, char **argv) {

   // stuff ..

   // Register callbacks
   glutSpecialFunc( OnSpecialKeys );  // Error, need static functions
   glutReshapeFunc( OnChangeSize );   // Error...
   glutDisplayFunc( OnRenderScene );  // Error...

   // stuff ..
}

GlutController::~GlutController() {

}

void GlutController::OnChangeSize(int aNewWidth, int aNewHeight){

   glViewport(0,0,aNewWidth, aNewHeight);
   mViewFrustrum.SetPerspective( APP_CAMERA_FOV,             // If this function is 
            float( aNewWidth ) / float( aNewHeight ),        // static, this won't 
            APP_CAMERA_NEAR,                                 // work
            APP_CAMERA_FAR );
   mProjectionMatrixStack.LoadMatrix(                        // Same here
            mViewFrustrum.GetProjectionMatrix() );
   mTransformPipeline.SetMatrixStacks(mModelViewMatrixStack, // Same here  
            mProjectionMatrixStack);

}

void GlutController::OnRenderScene(void){
   mGeometryContainer.draw();                                // Won't work if static
}

void GlutController::OnSpecialKeys(int key, int x, int y){
   mGeometryContainer.updateKeys(key);                       // Won't work if static
}

Disclaimer : I just begun C++. I read all of Accelerated C++ and this is my first project to try out the language. My background is in Java.

like image 567
AntoineG Avatar asked Aug 03 '12 09:08

AntoineG


4 Answers

What you are trying to do is not possible. This is glut's fault actually.

The thing is this:

  • glut wants to call a function, without giving it data,
  • You want your function to use some data,

which are conflicting needs. I believe glut decided you can safely use global variables.

So, one solution is to use static functions, with static data. Or a better solution would be to switch to SDL.

like image 152
Shahbaz Avatar answered Oct 11 '22 13:10

Shahbaz


In short, you can't. C++ member functions are actually 'linked' to the instance of the object. On the lower level, they have one extra parameter, which is actually the pointer to the instance of this object.

So, you have to use static function, and, since glut wouldn't let you to pass a parameter which would identify the current instance, you will have to come up with some workaround. The simplest workaround would be to use static members. If your GlutController is singleton (and I think it is), you'll be fine.

like image 36
Senna Avatar answered Oct 11 '22 13:10

Senna


It is possible and apparently safe to use a file scoped static variable pointing to your GlutInstance (static function + static data, like mentioned in another answer).

static GlutController* s_this;

static void s_OnChangeSize(int w, int h) { s_this->OnChangeSize(w, h); }

GlutController::GlutController (int argc, char **argv) { 
   s_this = this;

   glutSpecialFunc(s_OnSpecialKeys);
}

GlutController::~GlutController() { s_this= 0; } 

void GlutController::OnChangeSize(int w, int h) { /* non-static stuff */ }

s_this is only visible in the local file, e.g. not visible to any code that invokes the GlutController constructor from another file.

like image 39
Nick Avatar answered Oct 11 '22 14:10

Nick


you should have a static method and an instance (possibly static) to call a member function of instance from static function

Something like this:

//static method
void MyClass::myCallback()
{
    static MyClass instance; //or you can store your in instance in some Singleton, or
    //possibly create a temporary
    instance.nonStaticMethod();
}
like image 38
Andrew Avatar answered Oct 11 '22 13:10

Andrew