Могут ли лямбды GLFW принимать аргументы захвата? - PullRequest
0 голосов
/ 02 февраля 2020

Я создаю GLFWKeyCallback и из-за того, насколько это просто, я решил использовать лямбду. Этот обратный вызов изменяет переменную-член, поэтому я должен передать this в список захвата. Вот как выглядит мой код:

glfwSetKeyCallback(window, 
        [this](GLFWwindow* window, int key, int scancode, int action, int mods)
        {
            if(action == GLFW_PRESS)
            {
                 //use a mutex
                 //Modify member variable
            }
        });

Проблема в том, что всякий раз, когда я передаю this в список захвата, Visual Studio 2019 отображает следующую ошибку:

нет подходящей функции преобразования из "lambda [] void (GLFWwindow * окно, ключ int, int scancode, int action, int mods) -> void" в GLFWKeyfun "существует

Имеют Я что-то пропустил или этот код просто недействителен?

1 Ответ

2 голосов
/ 02 февраля 2020

Обратные вызовы GLFW не принимают лямбды или функциональные объекты: они используют простые старые указатели на функции. Не захватывающая лямбда может быть преобразована в указатель функции, но не в захватывающий.

Однако вы можете получить аналогичный эффект, используя glfwSetUserPointer и glfwGetUserPointer. Лямбда все еще не может быть захвачена, но вы можете восстановить указатель this.

Например,

struct MyClass {
  GLFWwindow* window;

  MyClass(GLFWwindow* window) : window(window) {
    glfwSetWindowUserPointer(window, static_cast<void*>(this));

    glfwSetKeyCallback(window, 
      [](GLFWwindow* window, int key, int scancode, int action, int mods) {
        auto self = static_cast<MyClass*>(glfwGetWindowUserPointer(window));
        // can access member variables through `self`
      });
  }

  // make sure that either the class will last as long as GLFW will
  // or clean up the user pointer and callbacks in here
  ~MyClass() {
    // clean up
  }

  // don't be able to copy, probably, or bad things will happen
  MyClass(const MyClass&) = delete;
  MyClass& operator=(const MyClass&) = delete;
  // other things...
};
...