Passing member functions to C functions?

Discussion in 'C++' started by Steven T. Hatton, Oct 4, 2004.

  1. I am trying to convert some basic OpenGL code to an OO form. This is the C
    version of the program:

    http://www.opengl.org/resources/code/basics/redbook/double.c

    You can see what my current effort at converting that code to an OO form
    looks like in the code listed below. The problem I'm running into is that
    the OpenGL functions that take the names of other functions as arguments
    don't like the way I'm passing the member functions of my class. I started
    out making all member functions non-static, but couldn't figure out a way
    to pass them to functions such as glutDisplayFunc(&GlutMain::display);

    Is there a way to accomplish this?

    #ifndef GLUTMAIN_HH
    #define GLUTMAIN_HH

    #include <GL/glut.h>
    namespace sth {
    namespace vmathGL {
    class GlutMain {
    public:

    GlutMain(int argc, char* argv[]);

    virtual ~GlutMain();

    void run();

    static void init();

    static void display();

    static void reshape(int w, int h);

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

    static void key(unsigned char k, int x, int y);

    static void spinDisplay();
    private:
    static GLfloat _spin;
    };
    }
    }
    #endif

    #include "GlutMain.hh"

    #include <cstdlib>

    namespace sth {
    namespace vmathGL {
    GlutMain::GlutMain(int argc, char* argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(250,250);

    }

    GlutMain::~GlutMain()
    {

    }

    void GlutMain::run()
    {
    init();
    glutDisplayFunc(&GlutMain::display); // compiles but segfaults.

    /*
    glutReshapeFunc(&reshape);
    glutMouseFunc(&mouse);
    glutMainLoop();
    */
    }

    void GlutMain::display()
    {
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    glRotatef(_spin, 0.0, 0.0, 1.0);
    glColor3f(1.0, 1.0, 1.0);
    glRectf(-25.0, -25.0, 25.0, 25.0);
    glPopMatrix();
    glutSwapBuffers();
    }

    void GlutMain::init()
    {
    glClearColor (0.0, 0.0, 0.0, 0.0);
    glShadeModel (GL_FLAT);
    }

    void GlutMain::reshape(int w, int h)
    {
    glViewport (0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }

    void GlutMain::mouse(int button, int state, int x, int y)
    {
    switch (button) {
    case GLUT_LEFT_BUTTON:
    if (state == GLUT_DOWN)
    glutIdleFunc(spinDisplay);
    break;
    case GLUT_MIDDLE_BUTTON:
    if (state == GLUT_DOWN)
    glutIdleFunc(NULL);
    break;
    default:
    break;
    }
    }

    void GlutMain::key(unsigned char k, int x, int y)
    {
    switch (k) {
    case 27: /* Escape */
    exit(0);
    break;
    default:
    return;
    }
    glutPostRedisplay();
    }

    void GlutMain::spinDisplay()
    {
    _spin = _spin + 2.0;
    if (_spin > 360.0)
    _spin = _spin - 360.0;
    glutPostRedisplay();
    }

    GLfloat GlutMain::_spin = 0.0;

    }
    }

    --
    "If our hypothesis is about anything and not about some one or more
    particular things, then our deductions constitute mathematics. Thus
    mathematics may be defined as the subject in which we never know what we
    are talking about, nor whether what we are saying is true." - Bertrand
    Russell
     
    Steven T. Hatton, Oct 4, 2004
    #1
    1. Advertising

  2. Steven T. Hatton

    David Hilsee Guest

    "Steven T. Hatton" <> wrote in message
    news:...
    > I am trying to convert some basic OpenGL code to an OO form. This is the

    C
    > version of the program:
    >
    > http://www.opengl.org/resources/code/basics/redbook/double.c
    >
    > You can see what my current effort at converting that code to an OO form
    > looks like in the code listed below. The problem I'm running into is that
    > the OpenGL functions that take the names of other functions as arguments
    > don't like the way I'm passing the member functions of my class. I

    started
    > out making all member functions non-static, but couldn't figure out a way
    > to pass them to functions such as glutDisplayFunc(&GlutMain::display);
    >
    > Is there a way to accomplish this?

    <snip>

    Well, you can't pass non-static member functions as a C callback. To invoke
    a non-static member function, you need an object, and C simply doesn't know
    how to invoke members on an object. The FAQ discusses this in 33.1, 2, and
    3.

    I think you might want to take a peek at the GlutMaster implementation
    (http://www.duke.edu/~stetten/GlutMaster/GlutMaster.html). It apparently
    uses the "window id" as a key for the corresponding callback object, so you
    could probably do something similar.

    --
    David Hilsee
     
    David Hilsee, Oct 5, 2004
    #2
    1. Advertising

  3. Markus Elfring, Oct 5, 2004
    #3
  4. Steven T. Hatton

    David Hilsee Guest

    "Markus Elfring" <> wrote in message
    news:...
    > > [...]
    > > Well, you can't pass non-static member functions as a C callback. To

    invoke
    > > a non-static member function, you need an object, and C simply doesn't

    know
    > > how to invoke members on an object. [...]

    >
    > http://parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
    >
    > Can function objects/functors also be used for the requested application?
    > http://en.wikipedia.org/wiki/Function_object


    If a library asks for a function pointer as a callback, then, no, you can't
    pass it a functor. C libraries often require function pointers and have no
    understanding of operator overloading, member functions, etc. The wikipedia
    entry is a little misleading because it doesn't mention that the sort
    function in the C example and the sort function in the C++ example are
    actually two different functions. It should have a declaration of sort() in
    each example.

    --
    David Hilsee
     
    David Hilsee, Oct 5, 2004
    #4
  5. > > http://parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
    > >
    > > Can function objects/functors also be used for the requested application?
    > > http://en.wikipedia.org/wiki/Function_object

    >
    > If a library asks for a function pointer as a callback, then, no, you can't
    > pass it a functor. C libraries often require function pointers and have no
    > understanding of operator overloading, member functions, etc. The wikipedia
    > entry is a little misleading because it doesn't mention that the sort
    > function in the C example and the sort function in the C++ example are
    > actually two different functions. It should have a declaration of sort() in
    > each example.


    Would you like to improve the article?

    Are the descriptions about "functionoids" relevant here?
    http://parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10
     
    Markus Elfring, Oct 6, 2004
    #5
  6. David Hilsee wrote:

    > Well, you can't pass non-static member functions as a C callback. To
    > invoke a non-static member function, you need an object, and C simply
    > doesn't know how to invoke members on an object. The FAQ discusses this in
    > 33.1, 2, and 3.


    Oh my! I got FAQed. For shame! ;)

    I actually had some problems with using static members as well, but don't
    recall the details. What I ended up doing was to create a global <blush>
    GlutMain* gmPtr and instantiating a corresponding object at the top of
    main(). Additionally, I replaced the bodies of the corresponding C
    functions with calls to gmPtr->functionName(/*args...*/). In the case where
    I had to deal with function pointers, I did this:

    void GlutMain::mouse(int button, int state, int x, int y, void(*spinDisp)())
    {
    switch (button) {
    case GLUT_LEFT_BUTTON:
    if (state == GLUT_DOWN)
    glutIdleFunc(spinDisp);
    break;
    case GLUT_MIDDLE_BUTTON:
    if (state == GLUT_DOWN)
    glutIdleFunc(NULL);
    break;
    default:
    break;
    }
    }

    My CVS server had a HD crash last week, so (alack and alas) I have not been
    keeping snapshots. I therefore don't have the corresponding version of
    spinDisp, but it was very similar to

    void spinDisp()
    {
    gmPtr->spinDisplay();
    }

    So I pass as an argument to a C++ member function, a pointer to a C
    (compatable under current conditions) function that invokes a C++ member
    function on the same object. The main() I ended up with looked very similar
    to the original redbook example with the addition of the object creation.

    How's /that/ for elegant simplicity? :D


    --
    "If our hypothesis is about anything and not about some one or more
    particular things, then our deductions constitute mathematics. Thus
    mathematics may be defined as the subject in which we never know what we
    are talking about, nor whether what we are saying is true." - Bertrand
    Russell
     
    Steven T. Hatton, Oct 6, 2004
    #6
  7. Steven T. Hatton

    David Hilsee Guest

    "Markus Elfring" <> wrote in message
    news:...
    > > >

    http://parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
    > > >
    > > > Can function objects/functors also be used for the requested

    application?
    > > > http://en.wikipedia.org/wiki/Function_object

    > >
    > > If a library asks for a function pointer as a callback, then, no, you

    can't
    > > pass it a functor. C libraries often require function pointers and have

    no
    > > understanding of operator overloading, member functions, etc. The

    wikipedia
    > > entry is a little misleading because it doesn't mention that the sort
    > > function in the C example and the sort function in the C++ example are
    > > actually two different functions. It should have a declaration of

    sort() in
    > > each example.

    >
    > Would you like to improve the article?
    >
    > Are the descriptions about "functionoids" relevant here?
    > http://parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10


    I added a few extra lines to the example to clarify. The functionoid is
    certainly relevant. The C++ example's actually pretty worthless because
    there is no way to supply something that implements the comparison function
    differently. Perhaps that should be the next enhancement (polymorphism or
    templates).

    --
    David Hilsee
     
    David Hilsee, Oct 7, 2004
    #7
  8. Steven T. Hatton

    David Hilsee Guest

    "Steven T. Hatton" <> wrote in message
    news:...
    > David Hilsee wrote:
    >
    > > Well, you can't pass non-static member functions as a C callback. To
    > > invoke a non-static member function, you need an object, and C simply
    > > doesn't know how to invoke members on an object. The FAQ discusses this

    in
    > > 33.1, 2, and 3.

    >
    > Oh my! I got FAQed. For shame! ;)


    Ah, there's no shame in being FAQed. I FAQ everyone. (Better make sure I
    pronounce that correctly)

    > I actually had some problems with using static members as well, but don't
    > recall the details. What I ended up doing was to create a global <blush>
    > GlutMain* gmPtr and instantiating a corresponding object at the top of
    > main(). Additionally, I replaced the bodies of the corresponding C
    > functions with calls to gmPtr->functionName(/*args...*/). In the case

    where
    > I had to deal with function pointers, I did this:
    >
    > void GlutMain::mouse(int button, int state, int x, int y,

    void(*spinDisp)())
    > {
    > switch (button) {
    > case GLUT_LEFT_BUTTON:
    > if (state == GLUT_DOWN)
    > glutIdleFunc(spinDisp);
    > break;
    > case GLUT_MIDDLE_BUTTON:
    > if (state == GLUT_DOWN)
    > glutIdleFunc(NULL);
    > break;
    > default:
    > break;
    > }
    > }
    >
    > My CVS server had a HD crash last week, so (alack and alas) I have not

    been
    > keeping snapshots. I therefore don't have the corresponding version of
    > spinDisp, but it was very similar to
    >
    > void spinDisp()
    > {
    > gmPtr->spinDisplay();
    > }
    >
    > So I pass as an argument to a C++ member function, a pointer to a C
    > (compatable under current conditions) function that invokes a C++ member
    > function on the same object. The main() I ended up with looked very

    similar
    > to the original redbook example with the addition of the object creation.
    >
    > How's /that/ for elegant simplicity? :D


    That works. GlutMaster's approach replaced your global with a table, which
    is a little better, but in the end, it's about the same, really. I'm
    somewhat surprised that the library didn't allow you to register a void* and
    a function pointer. That's a common practice that is very friendly to C++
    applications.

    --
    David Hilsee
     
    David Hilsee, Oct 7, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Newsgroup - Ann
    Replies:
    5
    Views:
    657
    John Carson
    Jul 30, 2003
  2. Replies:
    8
    Views:
    572
    PJP of NYC
    May 24, 2005
  3. Azdo
    Replies:
    2
    Views:
    453
  4. Hicham Mouline
    Replies:
    0
    Views:
    454
    Hicham Mouline
    Apr 23, 2009
  5. Hicham Mouline
    Replies:
    1
    Views:
    441
    Michael DOUBEZ
    Apr 24, 2009
Loading...

Share This Page