Normally I call this function like this

void MouseButton(int button, int state, int x, int y);
...
glutMouseFunc(MouseButton);

But now I would like to pass a member function instead of a "real" (non-member? whats the word for this?) function.

class Plot
{
  void Plot::MouseButton(int button, int state, int x, int y);
  ...
  Plot() { glutMouseFunc(MouseButton); }
}

But I get this error:

/home/dave/Plot/src/Plot.h:81: error: argument of type 'void (Plot::)(int, int, int, int)' does not match 'void (*)(int, int, int, int)'

What do I have to do differently to get this to work?

Thanks!
Dave

Assuming you have control over glutMouseFunc, you need to overload it to accept a pointer to a member function:

class Plot {
public:
  void MouseButton();
};

void glutMouseFunc ( void (Plot::*pmf)() )
{
  //...

  Plot p;
  (p.*pmf)();

  //...
}

I actually don't have control over glutMouseFunc (I mean I suppose I could edit the glut source, but that sounds like a bad idea)

Why is it so much different to pass a member function than a normal function?

Is there no way to do this without overloading glutMouseFunc?

Thanks!

Dave

I actually don't have control over glutMouseFunc (I mean I suppose I could edit the glut source, but that sounds like a bad idea)

Why is it so much different to pass a member function than a normal function?

Is there no way to do this without overloading glutMouseFunc?

Thanks!

Dave

You could just overload the function to accept a pointer-to-member function.

As I mentioned, I can't overload the function because it is not mine, it is in the glut library!

Non-static member function always called for the object, not in itself. The glutMouseFunc does not know, which object used for member function call. So it's no sense to pass a member function pointer to glutMouseFunc: it can't use such a pointer.

In other words, a pointer to a function is an address but a pointer to a member function is (roughly speaking) an offset in a class member functions table. The gkutMouseFunc wants address only.

I see, that makes sense.

What I was trying to do was this:

make a Plot class that would have all mouse selection routines (like rotation and zooming) defined and have everything else for opengl setup but then have a virtual Display() function so the user can override what actually gets plotted.

How else would I go about doing this since I have to provide glutMouseFunc and glutDisplayFunc with function pointers to be used when those callbacks are called?

Thanks,
Dave

>How else would I go about doing
Use a static member function, or provide a non-member helper that does what you want.

Hi all!
I have exactly the same problem! How can I solve it?
I tried to change the member function in a static member function, or to move the member function outside the class, or to use a global wrapper, or to use a delegate function, but I can not reach to a solution :-(

here is my simple code (using the static member function option):

class OGL {
   ...
   void init(void) {
      ...
      glutMouseFunc(mouse);
      ...
   }
   static void mouse(int button, int state, int x, int y) {
      ...
   }
   ...
}

what is wrong?

What error are you getting?
The problem with both of those solutions, in my opinion, is that you then cannot access member variables, which was my whole point of doing this in a class! (the display() function can only take certain parameters, so you cannot pass it anything else, you have to make the information global.)

Does this make sense?

using static member function, I get this error: "error C2664: 'glutMouseFunc' : cannot convert parameter 1 from 'void (__clrcall *)(int,int,int,int)' to 'void (__cdecl *)(int,int,int,int)'" (I use Visual Studio..)
How did you solve the problem?

ps: about display function, in my opinion I don't have that problem. I need glutMouseFunc only to get a single point, and so to set x and y coords. my display function is independent from mouse clicks :)

Your basic problem is that you need to ensure two bits of information come together: the object to be acted on (eg a pointer to that object) and the function to act on it (eg the member function).

glutMouseFunc(MouseButton) only passes information about the function to be called. That function somehow needs to find an object to act on, and then invoke a member function on that object.

Somewhere your MouseButton() function needs to do this;

some_object->some_member_function(some_arguments);

The problem is, you're doing nothing to pass information about "some_object" (eg a pointer to an object) to that function.

The reason the compiler complains when you try to pass a non-static member function is that a member function declared with 4 arguments is (to the compiler) a function with five arguments. The fifth (hidden) argument is a pointer or reference to the object being acted on. The callback point (the code where the function passed to glutMouseFunc() is called) does not have any information about what object to act on, so can do nothing with a non-static member function.

Narue's suggestion of using a global is one option: essentially your global callback needs to access an object from somewhere so it can call a member function on that object.

function pointer is different from member function pointer; the one is an address, while the other is an offset. I know the WHY.. now I need the HOW :D
I tried also the global option

class OGL {
   ...
   void init(void) {
      ...
      glutMouseFunc(mouse);
      ...
   }
   ...
};
void mouse(int button, int state, int x, int y) {
   ...
}

errors I get : "'mouse' : undeclared identifier" and "'mouse' : redefinition; previous definition was 'formerly unknown identifier'"

Now, I moved global function before the class. It compiles, but the linker give me: "stdafx.obj : error LNK2005: "void __cdecl mouse(int,int,int,int)" (?mouse@@YAXHHHH@Z) already defined in ABC.obj"

declaring mouse function as static (as indicated in msdn reference), the application crashes before to start :'(

function pointer is different from member function pointer; the one is an address, while the other is an offset. I know the WHY.. now I need the HOW :D

If you read previous posts carefully, you will realise you've been given information on HOW.

errors I get : "'mouse' : undeclared identifier" and "'mouse' : redefinition; previous definition was 'formerly unknown identifier'"

You need to place a declaration of the function in code that the compiler sees before you attempt to pass it as an argument.

Now, I moved global function before the class. It compiles, but the linker give me: "stdafx.obj : error LNK2005: "void __cdecl mouse(int,int,int,int)" (?mouse@@YAXHHHH@Z) already defined in ABC.obj"

That just means you have two source files that define (ie implement) the mouse() function. Remove one of those implementations.

mouse function is not defined into two files.. what can I do?

daviddoria, have you solved the problem?

mouse function is not defined into two files.. what can I do?

That error occurs also if you have implemented the mouse() function in a header file (.h) and include that header file in two or more source files (.cpp). So, you should move the implementation of the mouse() function to a single source file.

Nope, I don't think it can be done the way I would like. I got it to compile with a static member function, but then I can't access non static data members, so that defeats the point!

thanks ;)

in h file:

void mouse (int button, int state, int x, int y);

public ref class OGL{
   ...
   GLvoid InitGL(GLvoid);
   ...
};

in cpp file:

GLvoid mouse(int button, int state, int x, int y) {
   ...
}

GLvoid OGL::InitGL(GLvoid) {
   ...
   glutMouseFunc(mouse);
   ...
}

...

now, compiler and linker are ok, but.. I get "System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at glutMouseFunc(IntPtr )"
what's the next step?

This article has been dead for over six months. Start a new discussion instead.