tags:

views:

82

answers:

3

Hi. I want to pass Resize method of my Foo class object as the argument of glutReshapeFunc() but I get that error. How should I pass it?

This is my definition of Resize:

class Foo{
    public:
    void Resize(int w, int h);
    ...
}

and this is how I try to call it

glutReshapeFunc(foo->Resize);

It was ok when foo was not a pointer, I use to pass foo.Resize and it worked.

Thanks in advance

+4  A: 

Non-static functions take an additional hidden parameter (this) so they're not compatible with a global, non-member, function with apparently similar signature.

You could make Resize a static, but you'll have problem figuring out on what object to act. glutReshapeFunc mentions that

Before the callback, the current window is set to the window that has been reshaped.

so you can start from there in your static member.

Remus Rusanu
Same comment as Martin made on sje397's answer: actually you need to pass a pointer to a function with C linkage if it's to be called back from C code, and static member functions cannot be specified by the program to have C linkage. It may (let's face it, probably will) be the case that in your implementation calling a static member function as if it had C linkage "just works", and it may (let's face it, probably won't) be the case in your implementation that `glutReshapeFunc` was compiled as C++, either of which would save you.
Steve Jessop
+1  A: 

foo->Resize by itself is not a valid expression in C++. So, your code is flat out invalid. The only way to obtain a pointer to a non-static member function in C++ is to explicitly use the & operator and to explicitly use the qualified name of the member function. In your case that would be &Foo::Resize.

However, this is all beside the point, since you apparently need a pointer to an ordinary function not to a member function. A pointer to a member function is an object of completely different nature not even remotely similar to a pointer to an ordinary function. In other words, what you are trying to do is impossible. You can't pass a pointer to your Foo::Resize to glutReshapeFunc regardless of what you do.

If you want to call a non-static member function as a callback, it is your responsibility to use some kind of intermediate wrapper function that will receive the call and delegate it to the member function through a proper object. C++ by itself provides no good features for that, but it often can be implemented using specific features of the library you are trying to use (assuming the library is designed with that in mind).

AndreyT
+1  A: 

What you need is to map the current window to the foo object that represents that window (assuming you have one foo object per Window).

If you only have one foo object or you think of making the method static then stop. This is a C library and thus des not understand the C++ ABI. Switch your code back to using C functions. If your code is written in C++ files (or compiled as C++) then you must declare the functions as extern "C" to make sure that the bindings are correct.

If you have a Foo object for each window then I would do this:

std::map<int,Foo*>   myFoo;

extern "C" void myWindowRsize(int width, int height);

myInitGlut()
{
    // Do Init stuff
    glutReshapeFunc(&myWindowRsize);
}

myCreateWindow(std::string const& name)
{
    // When a window is created store the mapping:
    winID =  glutCreateWindow(name.c_str());

    // Now we have a new Foo for each window
    // Note this code is not complete myFoo should manage the objects this suggests
    // using a container of smart pointers or a smart container see boost for details.
    myFoo[winID] = new Foo();
}

// Your static resize function called for all windows
void myWindowRsize(int width, int height)
{
    // Get the current window. Then get the foo object for that windows.
    int   currentWindow = glutGetWindow();
    Foo*  windowsFoo    = myFoo[currentWindow];

    // Call your resize method.
    windowsFoo->Resize(width, height);
}
Martin York