如何修复按键回调函数和 glfwSetKeyCallback 之间的参数类型不匹配问题?

问题描述 投票:0回答:1

我创建了一个

Camera
类,其中包含
std::map<int, void(Camera::*)()
的键盘映射,以方便游戏中的键绑定选项和比使用 switch 语句可以完成的更高性能的键操作查找。

我无法使用

glfwSetKeyCallback
函数从键盘映射访问操作功能,并且我一直遇到 keyCallback 函数和
GLFWkeyfun
之间的签名不匹配的情况。

这是

Camera
课程:

class Camera {
    Camera();
private:
    void Mouse_Input();
    void Joystick_input();
    void keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods);

    void forward() {
        position += velocity * Orientation;
    }
    void backward() {
        position -= velocity * Orientation;
    }
    void left() {// Left
        position -= velocity * glm::normalize(glm::cross(Orientation, Up));
    }
    void right() {
        position += velocity * glm::normalize(glm::cross(Orientation, Up));
    }
    void up() {
        position += velocity * Up;
    }
    void down() {
        position -= velocity * Up;
    }
    void sprint() {
        velocity *= 2.f;
    }

    void noclip() {
        noClip = !noClip;
        if (!noClip) {
            gravity(position, velocity);
        }
    }
    void close() {
        glfwSetWindowShouldClose(Window::handle, true);
    }
public:
    alignas(16) glm::mat4 view;
    alignas(16) glm::mat4 proj;
    alignas(16) glm::vec3 position;

    void update(float FOVdeg, float nearPlane, float farPlane);
protected:
    bool noClip = true;
    bool firstClick = true;

    float velocity = 0.05f;
    float sensitivity = 1.75f;
    glm::vec3 Orientation;
    glm::vec3 Up;

    using pfunc = void (Camera::*)();
    std::map<int, pfunc> keyboard_map
    {
        { GLFW_KEY_W, &Camera::forward },
        { GLFW_KEY_A, &Camera::left },
        { GLFW_KEY_S, &Camera::backward },
        { GLFW_KEY_D, &Camera::right },
        { GLFW_KEY_SPACE, &Camera::up },
        { GLFW_KEY_LEFT_CONTROL, &Camera::down },
        { GLFW_KEY_LEFT_SHIFT, &Camera::sprint },
        { GLFW_KEY_V, &Camera::noclip },
        { GLFW_KEY_ESCAPE, &Camera::close }
    };
};

这些是我的 cpp 文件中的相关函数定义:

void Camera::keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods) {
    if (!GLFW_PRESS | !GLFW_REPEAT) {
        return;
    }
    auto afunc = keyboard_map[key];//gets camera action function from map
    (this->*afunc)();//executes action function
}
void Camera::update(float FOVdeg, float nearPlane, float farPlane)
{
    if (glfwJoystickPresent(GLFW_JOYSTICK_1)) {//Check for joystick
        std::jthread t_Console([&] { Joystick_input(); });
    }
    std::jthread t_PC([this] { glfwSetKeyCallback(Window::handle, &Camera::keyCallBack); }); //Line causing the error
    std::jthread t_mouse([&] { Mouse_Input(); });

    if (!noClip) {
        gravity(position, velocity);
    }
    view = glm::lookAt(position, position + Orientation, Up);
    proj = glm::perspective(glm::radians(FOVdeg), (float)GPU::Extent.width / GPU::Extent.height, nearPlane, farPlane);
    proj[1][1] *= -1;
}

我尝试了这个解决方案,它允许我编译程序,但是在调用

auto afunc = keyboard_map[key];
函数的
keyCallBack
行时,程序崩溃了,但没有产生错误代码。

std::jthread t_test([this]()
    {
        glfwSetKeyCallback(Window::handle,
        [](GLFWwindow* window, int key, int scancode, int action, int mods)
            {
                auto* instance = static_cast<Camera*>(glfwGetWindowUserPointer(window));
                if (instance) {
                    instance->keyCallBack(window, key, scancode, action, mods);
                }
            });
    }
);

我完全找不到这个问题的解决方案。有人可以帮助我理解为什么我的原始方法中存在签名不匹配,为什么访问地图会导致我尝试的其他方法崩溃,以及如何让此设置按预期工作?

编辑:错误:“

void(Camera::*)(GLFWwindow* window, int key, int scancode, int action, int mods)
类型的参数与
GLFWkeyfun
类型的参数不兼容”

c++ multithreading function-pointers glfw pointer-to-member
1个回答
0
投票

您正在尝试为您的 glfwSetKeyCallback() 回调使用

非静态
类方法。这是行不通的,因为
glfwSetKeyCallback()
需要一个 C 风格的函数指针。因此,您必须:

  • 使
    keyCallBack()
    保持静态
  • keyCallBack()
    类中完全删除
    Camera
    并将其设为独立函数
  • 正如您所发现的,
  • 使用非捕获 lambda。

无论哪种方式,正如您已经知道的,您都可以使用

glfwSetWindowUserPointer()
Camera*
指针存储到
GLWindow
中,然后在回调中使用
glfwGetWindowUserPointer()
返回到
Camera
对象。但是,您显示的代码没有在任何地方调用
glfwSetWindowUserPointer()

© www.soinside.com 2019 - 2024. All rights reserved.