Callback function in freeglut from object
Asked Answered
C

4

8

I'm using MSVC++ and freeglut in order to use openGL. Now, I have a class called Camera, which is pretty simple, but it also holds the function for the reshaping of my window.

My question is: how can I set glutReshapeFunc(void (*callback)(int,int)) to my function in my camera?

I have the following code, which won't work, because of a compiler error:

int main(int argc, char **argv)
{
    Camera *camera = new Camera();
    glutReshapeFunc(camera->ReshapeCamera);
}

and my Camera class looks like this in Camera.h:

class Camera
{
public:
    Camera(void);
    ~Camera(void);
    void ReshapeCamera(int width, int height);
};

Maybe this is just a more general callback question, but the only thing I found on the internet was creating some wrapper class around the callback. But it doesn't look like this should be so hard. Thanks in advance.

Cherisecherish answered 15/2, 2011 at 19:2 Comment(0)
H
10

There's no clean way to do this. C does not know about objects, so pointers-to-members don't work. C does not do templates, so functors don't work. The API does not even allow you to pass an arbitrary void *userData to your callback, so you can't pass the object around in that way either.

So, indeed, you'll have to create a wrapper function that is not a member function, and you'll have to give it access to the Camera object instance somehow, through a static and/or global variable.

If there can be multiple objects listening for this event, you could create a singleton class that allows you to register arbitrary listeners.

Hypaesthesia answered 15/2, 2011 at 19:9 Comment(0)
M
2

You can't connect it directly. ReshapeCamera is a member function, it needs a camera instance in order to run. The glut callback is a C function, which don't have an instance of camera to call your method. You need to create a function that call the camera reshape method.

Myrlemyrlene answered 15/2, 2011 at 19:8 Comment(0)
S
2

It has nothing to do with a "C vs C++" thing. You just need to understand what a member function call entails and basically what it compiles down to.

myObject.memberFunction(); // This is what the programmer sees.
memberFunction(&myObject); // This is what the compiler sees.

A member function is a fancy description of a function that simply takes the object as a first parameter. It's just invisible in the actual parameter list.

void MyClass::memberFunction() // This is the declaration the programmer sees.
void memberFunction(MyClass* this) // This is what the compiler sees.

From there, C++ adds special semantics to make it easy to work in an object-oriented fashion. So, even though your object has a member function of the format void(int, int), it actually has the format void(Camera*, int, int), and that does not match the desired format! This is why static function members can be used for such function pointers. Ever notice that static member functions cannot access the members of "this"? That is because static member functions do not pass an instance of the object representing "this".

In effect, you could emulate much of object-oriented programming in plain C. If you make a set of functions that take a struct pointer as the first parameter, you gain many of the same advantages!

Snelling answered 15/2, 2011 at 21:22 Comment(4)
So I created a static function in my class now, but it seems that it cannot convert from __thiscall to __decl. Error 1 error C2664: 'glutReshapeFunc' : cannot convert parameter 1 from 'void (__thiscall Camera::* )(int,int)' to 'void (__cdecl *)(int,int)'. And adding an explicit __cdecl gives a warning about the Camera::-part.Cherisecherish
@Marnix: The __thiscall suggests to me that glutReshapeFunc is not declared as static.Hypaesthesia
@Thomas: No the glutReshapeFunc is probably a function in C, the function coming from my Camera class is static, but has therefore another namespace. So it doesn't seem to get this.Cherisecherish
glutReshapeFunc(Camera::ReshapeCamera);Snelling
A
0

The following demonstrates how to register a c callback function from c++ Its generally useful, not specific to glut.

Here is your client c++ program

int main(int argc, char *argv[]) {

std::cout << "launching Camera ..." << std::endl;

Camera * camera = new Camera();

// ------ glut new window boilerplate ------- //

int WindowHandle = 0;
glutInit(&argc, argv);
WindowHandle = glutCreateWindow("hello there");
if(WindowHandle < 1) {
    std::cerr << "ERROR: Could not create a new rendering window" << std::endl;
    exit(EXIT_FAILURE);
}
// ------------------------------------------ //

camera->setup_callback();

glutMainLoop();

return 0;

}

Here is the Camera.cpp

Camera * ptr_global_instance = NULL;

extern "C" void ReshapeCamera_callback(int width, int height) {
    // c function call which calls your c++ class method
    ptr_global_instance->ReshapeCamera_cb(width, height);
}

void Camera::ReshapeCamera_cb(int width, int height) {
    std::cout << "width " << width << " height " << height << std::endl;
}

void Camera::setup_callback() {
    // c++ method which registers c function callback
    ::ptr_global_instance = this;
    ::glutReshapeFunc(::ReshapeCamera_callback);
}

and its header Camera.h

class Camera {
public:
    void ReshapeCamera_cb(int width, int height);
    void setup_callback();
};

Notice the use of a c++ global class pointer ptr_global_instance

Audacity answered 4/8, 2013 at 20:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.