PDA

View Full Version : Can i add parameters to the GLUT glutKeyboardFunc function?



darkenreaper57
03-03-2004, 03:20 PM
I want to pass in two class objects to the function "glutKeyboardFunc" (this is in addition to the required parameters), so that i can call functions based on those objects when a key is pressed. The objects are declared in main, and the data i want to access is private within the class. Can i do this? If not, what is a workaround? I really do not want to make the objects global, since my program is nearly finished and it is also bad practice (this is for school).

Thanks.

[This message has been edited by darkenreaper57 (edited 03-03-2004).]

nexusone
03-03-2004, 04:58 PM
Since glut is written in C, not sure you can to that.

A work around could be to declare a globel variable to access in the keyboard routine.



Originally posted by darkenreaper57:
I want to pass in two class objects to the function "glutKeyboardFunc" (this is in addition to the required parameters), so that i can call functions based on those objects when a key is pressed. The objects are declared in main, and are of type private within the class. Can i do this? If not, what is a workaround?

Thanks.

darkenreaper57
03-03-2004, 05:14 PM
Can you elaborate on the global variable idea? Any other ideas?

princeoflightning
03-04-2004, 03:45 AM
The parameter to the glutKeyboardFunc is the address of the function that needs to be invoked when a keystroke occurs.
Now your idea of having parameters passed to that function is totally against coding conventions. You are bound to have experienced compile-time errors like 'too many parameters'.. and so on.

There is a workaround that i suggest - have a class contain the call-back function (and possibly other relevant data and functions). Now whenever you need to register this particular call-back function you need to mention the address of the function- somewhat like this:
glutKeyboardFunc(thisobject.mykeyboard)

The syntax may be incorrect, but it should work since the conventions are being followed.

Most importantly, the class containing the registered call-back i.e. the class whose object is "thisobject" (see above) has some restrictions : it needs to have access to the other two objects mentioned (i suggest using the 'friend' idea of C++). Then, it is possible that dynamically allocated objects of the same class should not be created to avoid run-time errors.

Finally, I suggest going to a C++ forum rather than comeback here.

darkenreaper57
03-04-2004, 03:53 AM
before i change around most of my code...does anyone know if the syntax

glutKeyboardFunc(thisobject.mykeyboard)

is valid?

Thanks.

nexusone
03-04-2004, 04:51 AM
I am not very good a C++, but would define your class something like this:

#include<gl/gl.h>

//Define your class here

void keyboard (unsigned char key, int x, int y)
{
//write to or access your class here.
// functions to call, etc.

}



Originally posted by darkenreaper57:
Can you elaborate on the global variable idea? Any other ideas?



[This message has been edited by nexusone (edited 03-04-2004).]

princeoflightning
03-04-2004, 04:52 AM
The function header for c/c++ is:

glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))

nexusone
03-04-2004, 04:53 AM
No, see my next post.
As I stated because glut functions are C based, you can not overload them like in a C++ routine.


Originally posted by darkenreaper57:
before i change around most of my code...does anyone know if the syntax

glutKeyboardFunc(thisobject.mykeyboard) // Will not work.

is valid?

Thanks.

darkenreaper57
03-04-2004, 07:26 AM
Argh, its too hard to get around this problem...is there another toolkit other than glut that is more flexible? I want to be able to pass extra parameters into the keyboard function, such as objects. I also need to be able to do this to the display function.

nexusone
03-04-2004, 08:43 AM
You may want to look at SDL library in place of GLUT. www.libsdl.org (http://www.libsdl.org)

Or you can create your own window, keyboard routines.

Also look on the main page of this website, they have a listing of API's that you can use with openGL.


Originally posted by darkenreaper57:
Argh, its too hard to get around this problem...is there another toolkit other than glut that is more flexible? I want to be able to pass extra parameters into the keyboard function, such as objects. I also need to be able to do this to the display function.

Deiussum
03-04-2004, 09:49 AM
Originally posted by darkenreaper57:
before i change around most of my code...does anyone know if the syntax

glutKeyboardFunc(thisobject.mykeyboard)

is valid?

Thanks.

That would only be valid if mykeyboard is a static method. (Actually, I think you would have to use ClassName::MethodName) Anyway, if it is a static method, it cannot access any of the non-static methods of that class so that probably isn't what you want either.

Although, you could have a class with static objects and functions that could be used by the glut callback functions. Static objects aren't that much different from global ones, except in how they are referenced, though.

Ideally, for what you want, glut's keyboard function would take a void* parameter that could be used to pass extra data to your callback. (e.g. a pointer to the class you want to use...) However, it doesn't, and you'd have to modify glut in order to get this to work like that.

So... either make your objects global, static, or look for a different toolkit.

Deiussum
03-04-2004, 10:04 AM
So, just as a quick example of how to do this with static methods/objects, you would probably have something like so:




// smodel.h
class SClass
{
private:
static Object* pObject;

public:
static void Initialize();
static void DisplayCallback();
static void KeyboardCallback(unsigned char key, int x, int y);

};


// smodel.cpp
#include "smodel.h"

Object* SClass::pObject = NULL;

void SClass::Initialize()
{
SClass::pObject = new Object();
}

void SClass::DisplayCallback()
{
// yada yada
}

void SClass::KeyboardCallback(unsigned char key, int x, int y)
{
// yada yada
}

// main.cpp

#include <GL/glut.h>
#include "smodel.h"

// not complete, but you get the idea
int main(int argc, char** argv)
{
glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutCreateWindow("test");

SClass::Initialize();

glutKeyboardFunc(SClass::KeyboardCallback);
glutDisplayFunc(SClass::DisplayCallback);

glutMainLoop();

return 0;
}


Edit: disable smileys, dammit! :)


[This message has been edited by Deiussum (edited 03-04-2004).]

darkenreaper57
03-04-2004, 04:02 PM
Thanks a ton for all the info so far!
But what exactly does it mean when a function and/or object is static?
And Deiussum, are you basically saying i should use a sort of superclass to hold everything (btw, i am using C++, and i know very little C, mostly from my knowledge of C++)

[This message has been edited by darkenreaper57 (edited 03-04-2004).]

Deiussum
03-05-2004, 10:18 AM
Well.. when a member of a class is static, that basically means that every instance of that class uses the same memory space to access that memory. So if you have something like




class A
{
public:
static int n;
};


int A::n;

int main()
{
A a, b;

a.n = 2;
b.n = 3;

// This will output "3 3" becase A::n is
// "shared" between all instances of A.
cout << a.n << " " << b.n << endl;
}


Static member functions differ from normal member functions in that they do not have an implied "this" pointer as a parameter. It's because of the "this" pointer parameter that you cannot use standard class member functions as callbacks in glut. Because even though you may define them the same as what the callback prototype should be, underneath they are actually different.

You should also note that with static members and functions, you do not actually have to instantiate the class they belong to in order to access them. So in a sense, they are stored in a similar manner to global variables and functions, you just have to use the class name as a scope to access them.

chemdog
03-06-2004, 12:27 AM
In general, you must declare an



extern "C" {
...
}

block to define the methods you want to pass to GLUT.



glutDisplayFunc(SClass::DisplayCallback);


The above code shouldn't work even with static declarations, except in the most recent of C++ compilers. And there is no guarantee it will work tomorrow. And it probably will stop working once you add templates somewhere.

If you really want to access C++ declared functions, you should load them manually from a (so or dll) dynamic library and make sure you use the correct name mangling. OR you should create a C-function to properly access it.

If you want an object to respond then use something like this.



SClass* stuff = 0;//initialize me somewhere

extern "C" {
void KeyboardCallback(unsigned char key, int x, int y)
{
if stuff
stuff->vtbl->KeyboardCallback(stuff, key, x, y);
}
}


And if you want a class to respond then use something like this




extern "C" {
void KeyboardCallback(unsigned char key, int x, int y)
{
SClass::KeyboardCallback(key, x, y);//Make sure this is forward declared
}
}


Which even this second one, isn't guaranteed to work, but it will work more often than being able to take the address of a static member function.

Deiussum
03-06-2004, 07:14 AM
The above code shouldn't work even with static declarations, except in the most recent of C++ compilers. And there is no guarantee it will work tomorrow. And it probably will stop working once you add templates somewhere.


Ummm... yeah... I've been programming with C/C++ for many years now and pretty much every compiler I've ever used has allowed me to use static method functions as callbacks to C APIs. (Not just glut, but callback functions used in the Win32 API such as WndProc functions, etc.)

Your extern "C" stuff mostly is to avoid name mangling that C++ does in order to allow for things such as overloading functions. Since in this case you are actually giving it a pointer to the function, not a name, it really doesn't come into play as much.

I think the point you are trying to make is that there may be a different calling convention... With VC++ the default calling convention is __cdecl, which is what the glut callback functions look for. (Just because the functions are C++ doesn't mean that the calling convention can't be __cdecl... that only affects how parameters are passed to the function.)

From MSDN:


Place the __cdecl modifier before a variable or a function name. Because the C naming and calling conventions are the default, the only time you need to use __cdecl is when you have specified the /Gz (stdcall) or /Gr (fastcall) compiler option. The /Gd compiler option forces the __cdecl calling convention.


So, for MS compilers, if you may be using a different default calling convention, you can just use the __cdecl keyword on your static function.

Since I have never run into any problems using static functions as callbacks in the GNU compilers, I would assume that they also use a __cdecl calling convention by default. Though, there is probably a different keyword that would be used to force a function to have that calling convention as __cdecl is MS-specific. Like I said, I've never run into the problem with g++ before, so I've never had to try and figure out how to work around it.

darkenreaper57
03-07-2004, 07:21 AM
I basically understand what you guys are doing, but it looks like a lot of work to cope with GLUT. Is there a toolkit that is native to c++, so i can use objects easily? I looked at GLFW, and i think that might do the trick, but i am not sure.

I also prefer that this tookit is similar to glut in many ways. I dont want to have to restructure my entire program :\.

[This message has been edited by darkenreaper57 (edited 03-07-2004).]