5

I used the examples here to move my tessellation callbacks to a different class.

The code compiles, but the callback code never executes.

Callback Class:

template <class Class, typename ReturnType, typename Parameter>
class SingularCallBack
{
public:

    typedef ReturnType (Class::*Method)(Parameter);

    SingularCallBack(Class* class_instance, Method method)
        : class_instance_(class_instance),
        method_(method)
    {}

    ReturnType operator()(Parameter parameter)
    {
        return (class_instance_->*method_)(parameter);
    }

    ReturnType execute(Parameter parameter)
    {
        return operator()(parameter);
    }

private:

    Class* class_instance_;
    Method method_;
};

Callbacks:

void MyClass::tessBegin(GLenum which)
{
    glBegin(which);
    cout << "BEGIN CALLBACK IS WORKING";
}

void MyClass::tessVertex(const GLvoid *data)
{
    // cast back to double type
    const GLdouble *ptr = (const GLdouble*)data;

    glVertex3dv(ptr);
    cout << "VERTEX CALLBACK IS WORKING";
}

Tessellation function where I'm registering them:

int MyClass::TessellatePolys()
{
    GLUtesselator *tess = gluNewTess(); // create a tessellator
    if(!tess) return 0;  // failed to create tessellation object, return 0

    // register callback functions
    SingularCallBack<GLOrtho, void, GLenum>*BeginCallback;
    BeginCallback = new SingularCallBack<GLOrtho, void, GLenum>(this,&GLOrtho::tessBegin);
    gluTessCallback(tess, GLU_TESS_BEGIN, (void (CALLBACK *)())BeginCallback);

    SingularCallBack<GLOrtho, void, const GLvoid*>*VertexCallback;
    VertexCallback = new SingularCallBack<GLOrtho, void, const GLvoid*>(this,&GLOrtho::tessVertex);
    gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK *)())VertexCallback);

    ... (do tessellation) ...

    return id;
}

What is wrong with the way the callbacks are being registered?

BrickFrog
  • 71
  • 8
  • I'm not seeing how casting an object pointer to a function pointer is supposed to work. The way I'm reading it is that the tesselator will try to execute the data in `BeginCallback::class_instance_`, not dereference `BeginCallback` and run `operator()`. – genpfault Jan 09 '13 at 19:13
  • 9
    I see what you're saying. That part was my attempt to fit this solution (http://www.partow.net/programming/templatecallback/) into the tessellation code. Am I coming at the entire thing incorrectly? – BrickFrog Jan 09 '13 at 20:56
  • 1
    Kind of. The GLU tessellator is rather old code, and doesn't handle C++ objects the way you're trying. Making your callbacks just simple C-sytle functions will simplify many things. The [`gluTessCallback` man page](http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml) has a reasonable discussion of the callbacks and what you'll want to include in them (assuming you're familiar with immediate-mode-style OpenGL). – radical7 Jan 21 '13 at 17:09

1 Answers1

0

You are casting a pointer to an object type to a pointer to a function type (like, "BeginCallback" to "void (CALLBACK *)()"). These types are incompatible and unrelated. The code compiles as it is a c-style cast, without any type checking. Even more, from the C++ compiler point of view the BeginCallback and VertexCallback are different and incompatible types and the function gluTessCallback has no ability to call their overloaded operator() - these are different member functions.

Alexander B
  • 407
  • 2
  • 17