Вы используете неправильный подход со статическим классом пользовательского интерфейса. Обычный способ «отскочить» от статического обратного вызова к функции экземпляра - сохранить что-то, способное сделать переход, в месте, доступном из статического обратного вызова.
Большинство API, таких как GLFW и родной Win32, для которых требуются статические обратные вызовы такого рода, предоставляют способ для установления связи выше. В окнах GLFW есть блок памяти размером с указатель, который вы можете назначить: пользовательский указатель . Вы можете получить или установить этот указатель пользователя по мере необходимости.
Очень распространенный шаблон - иметь некоторый Game
класс, который имеет методы типа «HandleKeyPress (Key key)» или еще много чего. Когда вы запускаете программу, вы создаете Game
объект и выполняете всю инициализацию GLFW, а затем Game
вставляете указатель в хранилище пользовательских данных:
int main () {
GLFWindow * window = ... create GLFW window ...
Game game(... game constructor parameters ...);
glfwSetWindowUserPointer(window, &game);
... main game loop ...
}
Затем ваш обратный вызов с клавиатуры (и все другие статические обратные вызовы) может распаковать объект Game *
из хранилища указателя пользователя и переслать его:
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
Game * game = reinterpret_cast<Game *>(glfwGetWindowUserPointer(window);
game->HandleKeyDown(...);
}
HandleKeyDown
Метод по Game
примеру может переслать по вашему объекту пользовательского интерфейса , если это необходимо (или, если вы действительно только нужен ввод с клавиатурой для объекта UI можно просто засунуть указатель на объект пользовательского интерфейса в хранилище пользователя, однако, набивать что - то вроде игры или что-то более высокого уровня, как правило, лучше, так как у вас есть только один указатель на окно для использования).