mercredi 28 février 2018

Trampolining a non-static C++ member as a registered C callback

I am writing a C++ freeGlut 3.0.0 application. I am having trouble registering a generic callback signature (hopefully a function pointer template argument) with a non static member function that matches the signatures of the declared free-glut callbacks.

To this end, with the help from this answer, I put together a live Coliru working example that demonstrates how to register a C++ non static method as a callback with a C application (in my case the freeGlut library). A more modern C based normally would allow the callback registration to specify an optional void* user parameter which could be bound as a this* to the object with the callback member function as explained here. FreeGlut does not allow this in their callback registration API, so it seems that I will need to use a trampolining technique that I am not very familiar with.

My example uses a hard coded callback type alias callback_t with a specific signature. The place where I need help is to allow a more generic version of the callback type - perhaps the trampolining approach described in this [live coliru demo][5] could be used to modify my example as it takes a more generic approach. I suspect I need to change the callback_t below to somehow allow variadic arguments and a templated return type but I don't know how.

using callback_t = std::add_pointer<int(const char *, int)>::type;
using MyFTWFunction = std::function<void(unsigned char, int, int)>;

template <MyFTWFunction *callback>
class callback_binder {
public:
    static void trampoline(unsigned char key, int x, int y) {
        return (*callback)(key, x, y);
    }
};

// This matches the signature of the callbacks in freeGlut
extern "C" {
    // register the keyboard callback here
    void glutKeyboardFunc(void(*callback)(unsigned char ch, int x, int y)) {
        callback('S', 3, 4);
    }
    // register Reshape callback here
    void glutReshapeFunc(void(*callback)(int, int)) {
        callback(1, 2);
    }
    // register Display callback here
    void glutDisplayFunc(void(*callback)(void)) {
        callback();
    }
}

I need help making it more generic such that I can also register other callbacks.

Aucun commentaire:

Enregistrer un commentaire