Как использовать объект функции в качестве обратного вызова для вызова функций-членов (обработчиков) в объекте?
, которые я мог бы использовать в функциях glfwSet [...] Callback ().
Glfw не принимает указатели на функции-члены в качестве функций обратного вызова и не принимает функциональные объекты.
Вы можете зарегистрировать только указатели на функции.Указатели на функции не могут указывать на нестатические функции-члены.Перегрузка оператора вызова функции для объекта функции также является функцией-членом.
Вам необходимо написать функцию, не являющуюся членом (или вы можете использовать статическую функцию-член, если хотите), которая оборачивает вызов для членафункция (или объект функции, если вы предпочитаете).
Пример:
struct C {
void window_size(GLFWwindow*, int, int);
};
auto window_size_callback = [](GLFWwindow* window, int w, int h) {
C c;
c.window_size(window, w, h);
}; // a non-capturing lambda can be converted to a function pointer
// you can use a named function if you prefer
glfwSetWindowSizeCallback(window, window_size_callback);
Но, вероятно, вам нужен доступ к какому-то конкретному экземпляру класса (или объекту функции), а непо умолчанию построен один.В конце концов, зачем использовать нестатическую функцию-член, если это не так.Чтобы достичь этого, вам нужен какой-то способ передачи ссылки на этот объект в обратный вызов.
Способ, задокументированный GLFW:
Каждое окно имеет указатель пользователя, который может бытьустанавливается с glfwSetWindowUserPointer
и запрашивается с glfwGetWindowUserPointer
.Это может быть использовано для любых целей, которые вам нужны, и не будет изменяться GLFW в течение всего срока службы окна.
Если все ваши обратные вызовы должны вызываться для одного объекта, используйте этопрост:
C c;
glfwSetWindowUserPointer(window, &c);
auto window_size_callback = [](GLFWwindow* window, int w, int h) {
C* cptr = static_cast<C*>(glfwSetWindowUserPointer(window));
assert(c);
cptr->window_size(window, w, h);
};
К сожалению, API GLFW не поддерживает специфичные для обратного вызова пользовательские данные.Если вам нужны разные объекты для разных обратных вызовов, вы можете использовать свою собственную карту от обратного вызова до объекта, но это не так просто, как в примере выше.
Кроме того, будьте очень осторожны, чтобы сохранить объект как минимум живымдо тех пор, пока окно живое, чтобы обратные вызовы не вызывались по висячему указателю.