将成员函数传递给glfwSet * Callback

时间:2019-10-28 16:40:05

标签: c++ glfw

我正在尝试设置一个“事件接收器”类,以将GLFW回调包装为用户可以继承的类,但是在将基类成员函数传递给GLFW“设置回调”函数时遇到了问题。

#include <GLFW/glfw3.h>

//
//
//  Event Receiver Framework

enum EventTypes {
    Keyboard = 1,
    Mouse = 2
};

struct Event {
    EventTypes Action;
    //  Other Event Related Values
};

class EventReceiver {
    void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
        Event NewEvent;
        NewEvent.Action = EventTypes::Keyboard;
        OnEvent(NewEvent);
    }

public:
    virtual void OnEvent(Event& NewEvent) = 0;
};

//
//
//  Application Framework

class MyApplication {
    GLFWwindow* window;
public:
    void SetEventReceiver(EventReceiver* EventHandler) {
        glfwSetKeyCallback(window, &EventHandler->key_callback);
    }

};

//
//  
//  User-Defined Event Receiver

class MyEventReceiver : public EventReceiver {
public:
    void OnEvent(Event& NewEvent) {
        if (NewEvent.Action == EventTypes::Keyboard) {
            //  Custom Event Actions
        }
        else if (NewEvent.Action == EventTypes::Mouse) {
            //  Custom Event Actions
        }
    }
};

//
//
//  Main

int main() {
    MyEventReceiver _Events;
    MyApplication _App;
    _App.SetEventReceiver(&_Events);
    //
    //  Do logic
    //
    return 0;
}

这从根本上为基类提供了纯虚拟函数,供用户从事件中继承和重写以提供事件发生时自己的逻辑。用户定义的子类旨在传递给更大的“应用程序框架”类,该类进行必要的调用以设置GLFW回调函数。

当然,您不能将成员函数作为期望c-style-function的函数参数传递,因为您必须提供对类实例的访问权限,换句话说,必须提供类实例,以便调用成员函数知道将哪个对象用作“ this指针”。

对于GLFW中的'glfwSet * Callback'函数,我不确定该怎么做。

1 个答案:

答案 0 :(得分:0)

在GLFW中只能像这样使用静态成员函数,如果需要,可以使用glfwGetWindowUserPointer和glfwSetWindowUserPointer在这些情况下提供对基础类对象的访问。

#include <GLFW/glfw3.h>

//
//
//  Event Receiver Framework

enum EventTypes {
    Keyboard = 1,
    Mouse = 2
};

struct Event {
    EventTypes Action;
    //  Other Event Related Values
};


class EventReceiver {
    static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
        Event NewEvent;
        NewEvent.Action = EventTypes::Keyboard;
        static_cast<EventReceiver*>(glfwGetWindowUserPointer(window))->OnEvent(NewEvent);
    }

public:
    virtual void OnEvent(Event& NewEvent) = 0;
    friend class MyApplication;
};

//
//
//  Application Framework

class MyApplication {
    GLFWwindow* window;
public:
    void SetEventReceiver(EventReceiver* EventHandler) {
        glfwSetWindowUserPointer(window, EventHandler);
        glfwSetKeyCallback(window, &EventReceiver::key_callback);
    }

};

//
//  
//  User-Defined Event Receiver

class MyEventReceiver : public EventReceiver {
public:
    void OnEvent(Event& NewEvent) {
        if (NewEvent.Action == EventTypes::Keyboard) {
            //  Custom Event Actions
        }
        else if (NewEvent.Action == EventTypes::Mouse) {
            //  Custom Event Actions
        }
    }
};

//
//
//  Main

int main() {
    MyEventReceiver _Events;
    MyApplication _App;
    _App.SetEventReceiver(&_Events);
    //
    //  Do logic
    //
    return 0;
}