Thread: [GLUT] Pointers to class methods

  1. #1
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709

    [GLUT] Pointers to class methods

    I've created a little class which basically wraps up a little demo type thing I've written while following various GLUT tutorials and I need to make the calls to the "glutXFunc" (eg. glutDisplayFunc) but I'm stumped on how to give it a class method as a parameter.

    Here's the function - initGLUT () - which attempts to do this:

    Code:
    void initGLUT ()
    {
            glutInitDisplayMode (GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
            glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
    
            glutInitWindowPosition (0, 0);
            glutInitWindowSize (640, 480);
            glutCreateWindow ("Engine Demo");
            glEnable (GL_DEPTH_TEST);
    
            glutDisplayFunc (engineDemo::render);  // problem line
    
            // haven't tackled these yet so ignore them
            glutReshapeFunc (reshape);
            glutIdleFunc (render);
            glutKeyboardFunc (normalKeys);
            glutSpecialFunc (specialKeys);
            glutMouseFunc (mousePress);
            glutPassiveMotionFunc (mousePassiveMotion);
    }
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  2. #2
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    The syntax is pretty tortured:
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Dog
    {
    public:
    	string bark(int num)
    	{
    		for(int i = 0; i<num; i++)
    			cout<<"Woof!";
    
    		cout<<endl;
    		
    		return "I finished barking.";
    	}
    };
    
    void someFunc(const Dog& aDog, string(Dog::*pDogFunc)(int) )
    {
    	string result = (aDog.*pDogFunc)(3);
    	cout<<result<<endl;
    }
    
    int main()
    {
    	Dog myDog;
    	string(Dog::*pFunc)(int) = Dog::bark;
    	someFunc(myDog, pFunc);
    
    	return 0;
    }
    Last edited by 7stud; 02-15-2006 at 03:51 PM.

  3. #3
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Ok I've given it my best shot:

    Code:
    void initGLUT ()
    {
            void (engineDemo::*p_Render) (void) = engineDemo::render;
    
            glutInitDisplayMode (GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
            glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
    
            glutInitWindowPosition (0, 0);
            glutInitWindowSize (640, 480);
            glutCreateWindow ("Engine Demo");
            glEnable (GL_DEPTH_TEST);
    
            glutDisplayFunc (p_Render);
            glutReshapeFunc (reshape);
            glutIdleFunc (render);
            glutKeyboardFunc (normalKeys);
            glutSpecialFunc (specialKeys);
            glutMouseFunc (mousePress);
            glutPassiveMotionFunc (mousePassiveMotion);
    }
    EDIT: Oh yeah, the errors:

    Code:
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(283) : error C2664: 'glutDisplayFunc' : cannot convert parameter 1 from 'void (__thiscall engineDemo::* )(void)' to 'void (__cdecl *)(void)'
            There is no context in which this conversion is possible
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  4. #4
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    If you make the function inside the render class static you should be able to send it to glutDisplayFunc.
    STL Util a small headers-only library with various utility functions. Mainly for fun but feedback is welcome.

  5. #5
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Ok I'll try that quick.
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  6. #6
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    It sort of worked. There were probs except I've had to make everything in the class static and the linker threw up unresolved externals because I forgot to type static in front of all the definitions, but when I did that I now get these:

    Code:
    ------ Build started: Project: glutProj, Configuration: Debug Win32 ------
    
    Compiling...
    glutProj.cpp
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(98) : error C2724: 'engineDemo::renderString' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(107) : error C2724: 'engineDemo::playSound' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(118) : error C2724: 'engineDemo::setOrthoProjection' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(143) : error C2724: 'engineDemo::resetPerspectiveProjection' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(151) : error C2724: 'engineDemo::render' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(188) : error C2724: 'engineDemo::reshape' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(208) : error C2724: 'engineDemo::normalKeys' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(221) : error C2724: 'engineDemo::specialKeys' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(243) : error C2724: 'engineDemo::mousePress' : 'static' should not be used on member functions defined at file scope
    c:\Documents and Settings\lee\Desktop\glutProj\glutProj.cpp(265) : error C2724: 'engineDemo::mousePassiveMotion' : 'static' should not be used on member functions defined at file scope
    
    Build Time 0:00
    Build log was saved at "file://c:\Documents and Settings\lee\Desktop\glutProj\Debug\BuildLog.htm"
    glutProj - 10 error(s), 0 warning(s)
    
    
    ---------------------- Done ----------------------
    
        Build: 0 succeeded, 1 failed, 0 skipped
    I've never had these before.
    Oh yeah I don't understand how making them static 'makes it work'?
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  7. #7
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    Ok I guess that what it looks like now is something like this:
    Code:
    class Foo
    {
    public:
    	static void Test();
    };
    
    static void Foo::Test()
    {
    	// Bla bla bla bla
    }
    if so change it to this:
    Code:
    class Foo
    {
    public:
    	static void Test();
    };
    
    void Foo::Test()  // Note that static is not preceeding void here
    {
    	// Bla bla bla bla
    }
    STL Util a small headers-only library with various utility functions. Mainly for fun but feedback is welcome.

  8. #8
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    OK so now the linker can't see the class member data:

    Code:
    ------ Build started: Project: glutProj, Configuration: Debug Win32 ------
    
    Compiling...
    glutProj.cpp
    Linking...
    glutProj.obj : error LNK2001: unresolved external symbol "private: static class FMOD::Sound * engineDemo::m_Sound" (?m_Sound@engineDemo@@0PAVSound@FMOD@@A)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static enum FMOD_RESULT engineDemo::m_Result" (?m_Result@engineDemo@@0W4FMOD_RESULT@@A)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static class FMOD::System * engineDemo::m_FMOD_System" (?m_FMOD_System@engineDemo@@0PAVSystem@FMOD@@A)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static char * engineDemo::m_FPS" (?m_FPS@engineDemo@@0PADA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static char * engineDemo::m_Buffer" (?m_Buffer@engineDemo@@0PADA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static int engineDemo::m_Timebase" (?m_Timebase@engineDemo@@0HA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static int engineDemo::m_Time" (?m_Time@engineDemo@@0HA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static int engineDemo::m_Frame" (?m_Frame@engineDemo@@0HA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static int engineDemo::m_Height" (?m_Height@engineDemo@@0HA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static int engineDemo::m_Width" (?m_Width@engineDemo@@0HA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static float engineDemo::m_Blue" (?m_Blue@engineDemo@@0MA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static float engineDemo::m_Green" (?m_Green@engineDemo@@0MA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static float engineDemo::m_Red" (?m_Red@engineDemo@@0MA)
    glutProj.obj : error LNK2001: unresolved external symbol "private: static float engineDemo::m_Angle" (?m_Angle@engineDemo@@0MA)
    Debug/glutProj.exe : fatal error LNK1120: 14 unresolved externals
    
    Build Time 0:00
    Build log was saved at "file://c:\Documents and Settings\lee\Desktop\glutProj\Debug\BuildLog.htm"
    glutProj - 15 error(s), 0 warning(s)
    
    
    ---------------------- Done ----------------------
    
        Build: 0 succeeded, 1 failed, 0 skipped
    EDIT: Here's the class:

    Code:
    class engineDemo {
            static float   m_Angle;
            static float   m_Red;
            static float   m_Green;
            static float   m_Blue;
            static char    m_Buffer[30];
            static int     m_Width;
            static int     m_Height;
            static int     m_Frame;
            static int     m_Time;
            static int     m_Timebase;
            static char    m_FPS[10];
    
            static FMOD_RESULT     m_Result;
            static FMOD::System    *m_FMOD_System;
            static FMOD::Channel   *m_Channel;
            static FMOD::Sound     *m_Sound;
    
    public:
            engineDemo ();
            ~engineDemo ();
    
            static void    renderString (float x, float y, void *font, char *str);
            static void    playSound ();
            static void    setOrthoProjection ();
            static void    resetPerspectiveProjection ();
            static void    render ();
            static void    reshape (int w, int h);
    
            // GLUT handler functions
            static void    normalKeys (unsigned char key, int x, int y);
            static void    specialKeys (int key, int x, int y);
            static void    mousePress (int button, int state, int x, int y);
            static void    mousePassiveMotion (int x, int y);
    
    };
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  9. #9
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Sounds like you need to define them outside the class:
    Code:
    float engineDemo::m_angle;
    float engineDemo::m_Red  = 10; //you can initialize them as well
    Still, it seems bad design to me to have a class full of static members. Maybe (and take what I say with a grain of salt because I'm no design expert) you want to use the singleton design pattern instead. In that case, you could have a single static instance of the class as a member, which would be used to access the data
    Code:
    class engineDemo
    {
    float m_Angle;
    //etc
    static engineDemo m_instance;
    public:
      static engineDemo* Instance() { return &m_instance; }
      static void render();
      //other methods could be non-static if they don't need to be
      //passed as arguments to functions
    }
    If you do a google search you'll find plenty of information on singletons
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  10. #10
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Right I've found a couple of good articles thru google and I'm going to get this singletonised!
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  11. #11
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Ok so how do I define the member functions? Here's what I've got so far:

    Code:
    class Demo {
            float   m_Angle;
            float   m_Red;
            float   m_Green;
            float   m_Blue;
            char    m_Buffer[30];
            int     m_Width;
            int     m_Height;
            int     m_Frame;
            int     m_Time;
            int     m_Timebase;
            char    m_FPS[10];
    
            FMOD_RESULT     m_Result;
            FMOD::System    *m_FMOD_System;
            FMOD::Channel   *m_Channel;
            FMOD::Sound     *m_Sound;
    
    public:
            static Demo     *Instance ();
    
            static void     renderString (float x, float y, void *font, char *str);
            void            playSound ();
            void            setOrthoProjection ();
            void            resetPerspectiveProjection ();
            static void     render ();
            static void     reshape (int w, int h);
    
            // GLUT Handler functions
            static void     normalKeys (unsigned char key, int x, int y);
            static void     specialKeys (int key, int x, int y);
            static void     mousePress (int button, int state, int x, int y);
            static void     mousePassiveMotion (int x, int y);
    
    
    protected:
            Demo ();
            Demo (const Demo &);
            Demo &operator= (const Demo &);
    };
    And this is as far as I've gotten with implementation:

    Code:
    // playSound
    void playSound ()
    {
            m_Result = m_FMOD_System->playSound (FMOD_CHANNEL_FREE, m_Sound, false, 0);
            if (m_Result != FMOD_OK) {
                    MessageBox (0, "Error playing sound", "FMOD Error",
                                    MB_OK | MB_ICONEXCLAMATION);
                    exit (1);
            }
    }
    Errors:

    Code:
    ------ Build started: Project: engineDemo, Configuration: Debug Win32 ------
    
    Compiling...
    Demo.cpp
    c:\Documents and Settings\lee\Desktop\engineDemo\Demo.cpp(31) : error C2065: 'm_Result' : undeclared identifier
    c:\Documents and Settings\lee\Desktop\engineDemo\Demo.cpp(31) : error C2065: 'm_FMOD_System' : undeclared identifier
    c:\Documents and Settings\lee\Desktop\engineDemo\Demo.cpp(31) : error C2227: left of '->playSound' must point to class/struct/union
            type is ''unknown-type''
    c:\Documents and Settings\lee\Desktop\engineDemo\Demo.cpp(31) : error C2065: 'm_Sound' : undeclared identifier
    c:\Documents and Settings\lee\Desktop\engineDemo\Demo.cpp(32) : error C2679: binary '!=' : no operator found which takes a right-hand operand of type 'FMOD_RESULT' (or there is no acceptable conversion)
    c:\Documents and Settings\lee\Desktop\engineDemo\Demo.cpp(32) : error C3861: 'm_Result': identifier not found, even with argument-dependent lookup
    Generating Code...
    Compiling...
    engineDemo.cpp
    Generating Code...
    
    Build Time 0:00
    Build log was saved at "file://c:\Documents and Settings\lee\Desktop\engineDemo\Debug\BuildLog.htm"
    engineDemo - 6 error(s), 0 warning(s)
    
    
    ---------------------- Done ----------------------
    
        Build: 0 succeeded, 1 failed, 0 skipped
    Sorry to dump all this on the reader but I'm completely stumped.
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  12. #12
    User
    Join Date
    Jan 2006
    Location
    Canada
    Posts
    499
    Do you have a separate header file?

    (class.h)

    Code:
    class whatever {
    public:
    //your methods and data here
    };
    (class.cpp)

    Code:
    #include "class.h"
    
    // your method implementations here
    Hope this doesn't sound stupid.

  13. #13
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Yes I do have it in a .h & .cpp but I'd be surprised to learn that this is the problem
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  14. #14
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Don't you want:
    Code:
    void Demo::playSound ()
    {
            m_Result = m_FMOD_System->playSound (FMOD_CHANNEL_FREE, m_Sound, false, 0);
            if (m_Result != FMOD_OK) {
                    MessageBox (0, "Error playing sound", "FMOD Error",
                                    MB_OK | MB_ICONEXCLAMATION);
                    exit (1);
            }
    }
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Assign class action using function pointers....
    By BrownB in forum C++ Programming
    Replies: 3
    Last Post: 05-02-2007, 04:27 AM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  4. exporting class methods to library results in .lib and .exp
    By Shadow12345 in forum C++ Programming
    Replies: 15
    Last Post: 01-05-2003, 08:01 PM
  5. Replies: 4
    Last Post: 09-12-2001, 02:05 PM