当前位置: 首页 > 知识库问答 >
问题:

将成员函数传递给glfwSet*回调

颜永怡
2023-03-14

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

#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回调函数。

当然,您不能将成员函数作为函数参数传递,因为您必须提供对类实例的访问,或者换句话说,您必须提供类实例,以便被调用的成员函数知道使用哪个对象作为“this pointer”。

我不知道如何做到这一点在GLFW内部的glfwSet*回调函数。

共有1个答案

萧萧迟
2023-03-14

在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;
}
 类似资料:
  • 我编写了一个代码来传递函数指针列表(按其名称)作为参数。但我有错误。你能解释为什么我在做地图时有错误吗? 错误: 34:18:错误:无法将'void(Bar::)(int, int)'转换为'std::map, void(*)(int, int) 35:18:错误:无法将“无效(foo::)(整数,整数)”转换为“标准::映射,无效(*)(整数,整型) 41:70:错误:没有用于调用“std::v

  • 问题内容: 我试图将回调函数从控制器传递给指令。 这是回调函数代码: 指令用法: 指令代码: 模板中的回调用法: 但是,这给了我以下错误: 我看过很多类似的问题,但不明白我在哪里错了。 问题答案: 从指令中调用表达式方法时,您需要以格式传递指令中的参数,还应更正指令属性值以像 指令用法: 指令模板

  • 我在代码中使用STD::Thread时遇到问题: 我得到以下错误: 我的问题看起来像是重复的,但只有一点不同,在另一个问题的答案中,std::Thread是在类声明或实现之外使用的,它是在main()中使用的,在这种情况下,指定范围对我来说是有意义的,但当std::Thread在类内部调用时就没有意义了。这是我看到的唯一区别,也是为什么我做了这个线程,很抱歉可能会重复。

  • 问题内容: 我正在尝试将一些参数传递给用作回调的函数,该怎么做? 问题答案: 如果您想要更一般的东西,可以使用arguments变量,如下所示: 但是否则,您的示例可以正常工作(可以在测试器中使用arguments [0]代替回调)

  • 我试图构造一个包含可选闭包的表。当我尝试实例化表的实例时,传递闭包的成员函数,我会得到一个编译错误。 从错误 msg 中可以看出,成员函数无法转换为可选的成员函数。我不明白为什么不;Int 或其他类型可以很容易地转换为可选类型。 无法转换类型为“”的值-

  • 问题内容: 我需要在Node.JS应用程序中观察少量目录: 问题在于fs.watch仅将文件名传递给回调函数,而没有包括它所在的目录。我是否可以通过某种方式将额外的参数传递给updated()函数,以便它知道文件在哪里? 我认为我正在寻找类似于Python的工具,如果有帮助的话。 问题答案: 您可以使用: