Skip to main content
Code Review

Return to Question

Post Reopened by Sᴀᴍ Onᴇᴌᴀ , alecxe, Toby Speight, Ludisposed, Mast
State the objective in the title, not the concerns
Link
Toby Speight
  • 87.9k
  • 14
  • 104
  • 325

Optimal way to use C++ wrapper for GLFW callbacks inside classeswindow object

update grammar, spelling
Source Link

ImI'm creating a window class in C++ to provide a bit of abstraction for a GLFW window.

The code works as intended. ImI'm really new to c++ thothough and I assume there isare tons iI could improve about this class, not just in terms of speed, but also structure.

ImI'm especially concerned with the way I get around the fact that GLFW callbacks are static. In my callbacks I want to accesaccess methods in my class and so I create a pointer to the actual 'window user' using glfwGetWindowUserPointer, to accesaccess the actual class methods an member variables.

Still i'mI'm just looking for any thoughtthoughts on how to improve this code.

Im creating a window class in C++ to provide a bit of abstraction for a GLFW window.

The code works as intended. Im really new to c++ tho and I assume there is tons i could improve about this class, not just in terms of speed, but also structure.

Im especially concerned with the way I get around the fact that GLFW callbacks are static. In my callbacks I want to acces methods in my class and so I create a pointer to the actual 'window user' using glfwGetWindowUserPointer, to acces the actual class methods an member variables.

Still i'm just looking for any thought on how to improve this code.

I'm creating a window class in C++ to provide a bit of abstraction for a GLFW window.

The code works as intended. I'm really new to c++ though and I assume there are tons I could improve about this class, not just in terms of speed, but also structure.

I'm especially concerned with the way I get around the fact that GLFW callbacks are static. In my callbacks I want to access methods in my class and so I create a pointer to the actual 'window user' using glfwGetWindowUserPointer, to access the actual class methods an member variables.

Still I'm just looking for any thoughts on how to improve this code.

added 3716 characters in body; edited tags
Source Link
Cortex
  • 440
  • 3
  • 16

Im creating a window class in C++ to provide a bit of abstraction for a GLFW window. To me it makes sense to add a key_callback as a method in my class. The issue is ofcourse that GLFW is written in C, and so it requires callbacks to be static.

I found that GLFW has a glfwSetWindowUserPointer function that sets:

.. sets the user-defined pointer of the specified window.. ----- Docs

So I went with the following solution:

In my windowwindow.h:

#pragma once
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
class Window {
 GLFWwindow* window;m_Window;
 //GLFWmonitor* Morem_Monitor;
 members.. const char* m_Title;
 GLFWimage m_Icon[1];
 int m_Width, m_Height;
 int m_PosX, m_PosY;
  bool m_Fullscreen;

public:
 Window(...int width, int height, const char* title, const char* iconPath); // Constructor ~Window();
 GLFWwindow* getWindow();
 const char** getRequiredExtensions();
private:
 //void Stuff...queryVulkanSupport();
 void setKeyCallbackinitGLFW(); // Function to setvoid keycallbackcreateWindow();
 void setIcon(const char* path);
 void center();
 void setFullscreen();
 void setWindowSizeCallback();
 static void static_KeyCallbackstatic_WindowSizeCallback(GLFWwindow* window, int keywidth, int scancode,height);
  void windowSizeCallback(int actionwidth, int modsheight); // The static keycallbackvoid setKeyCallback();
 static void keyCallbackstatic_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // Non static keycallbackvoid keyCallback(int key, int scancode, int action, int mods);
};

In my windowwindow.cpp:

#include "window.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#include <stdexcept>
#include <string>
Window::Window(...int width, int height, const char* title, const char* iconPath) : m_Fullscreen(false), m_Width(width), m_Height(height), m_Title(title) {
 glfwSetWindowUserPointerinitGLFW(window,);
 this queryVulkanSupport();
 m_Monitor = glfwGetPrimaryMonitor();
 createWindow();
 setIcon(iconPath);
 setWindowSizeCallback();
 setKeyCallback();
}

Window::~Window() {
 // moreglfwDestroyWindow(m_Window);
 stuff glfwTerminate();
}
GLFWwindow* Window::getWindow() {
 return m_Window;
}
const char** Window::getRequiredExtensions()
{
 uint32_t count;
 const char** extensions = glfwGetRequiredInstanceExtensions(&count);
 return extensions;
}
void Window::setKeyCallbackqueryVulkanSupport() {
 glfwSetKeyCallbackif (!glfwVulkanSupported()) {
 throw std::runtime_error("Vulkan not supported!");
 }
}
void Window::initGLFW() {
 if (!glfwInit()) {
 throw std::runtime_error("Failed to initialize GLFW!");
 }
}
void Window::createWindow() {
 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
 m_Window = glfwCreateWindow(m_Width, m_Height, m_Title, nullptr, nullptr);
 if (!m_Window) {
 throw std::runtime_error("Could not create GLFW window!");
 }
 glfwSetWindowUserPointer(m_Window, static_KeyCallbackthis); / center();
}
void Window::setIcon(const char* path) {
 m_Icon[0].pixels = stbi_load(path, &m_Icon[0].width, &m_Icon[0].height, 0, 4);
 if (m_Icon[0].pixels)
 glfwSetWindowIcon(m_Window, 1, m_Icon);
}
void Window::center() {
 const GLFWvidmode* vidMode = glfwGetVideoMode(m_Monitor);
 glfwSetWindowPos(m_Window, (vidMode->width - m_Width) / Set2, keycallback(vidMode->height to- staticm_Height) member/ function2);
}
void Window::static_KeyCallbacksetFullscreen(GLFWwindow*) window{
 if (!m_Fullscreen) {
 const GLFWvidmode* vidMode = glfwGetVideoMode(m_Monitor);
 glfwGetWindowPos(m_Window, int&m_PosX, key&m_PosY);
 glfwGetWindowSize(m_Window, int&m_Width, scancode&m_Height);
 glfwSetWindowMonitor(m_Window, m_Monitor, 0, 0, vidMode->width, vidMode->height, vidMode->refreshRate);
 glfwSetWindowSize(m_Window, vidMode->width, vidMode->height);
 m_Fullscreen = !m_Fullscreen;
 }
 else {
 glfwSetWindowMonitor(m_Window, nullptr, m_PosX, m_PosY, m_Width, m_Height, 0);
 glfwSetWindowSize(m_Window, m_Width, m_Height);
 m_Fullscreen = !m_Fullscreen;
 }
}
void Window::setWindowSizeCallback() {
 glfwSetWindowSizeCallback(m_Window, static_WindowSizeCallback);
}
void Window::static_WindowSizeCallback(GLFWwindow* window, int actionwidth, int modsheight) {
 Window* actualWindow = (Window*) glfwGetWindowUserPointer(window); // Get a pointeractualWindow->windowSizeCallback(width, toheight);
}
void theWindow::windowSizeCallback(int windowwidth, instanceint thatheight) has{
 the actual window. glfwSetWindowSize(m_Window, width, height);
}
void Window::setKeyCallback() {
 actualWindow->keyCallbackglfwSetKeyCallback(m_Window, static_KeyCallback);
}
void Window::static_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); //{
 Acces that actual Window* actualWindow = (Window*) glfwGetWindowUserPointer(window);
 instanceses method actualWindow->keyCallback(key, scancode, action, mods);
}
void Window::keyCallback(int key, int scancode, int action, int mods) {
 if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
 glfwSetWindowShouldClose(m_Window, true);
 if (key == GLFW_KEY_F11 && action == GLFW_RELEASE)
 setFullscreen();
}

main.cpp

#include "window.h"
int main() {
 Window window(600, 300, "Vulkan engine!", "include/Ressources/VulkanIcon.png");
 Do stuff. while (!glfwWindowShouldClose(window.getWindow())) {
 glfwPollEvents();
 }
}

The primary reason that I need(or would like) the callbackcode works as intended. Im really new to be nonstatic is becausec++ tho and I want to use methods from the Windowassume there is tons i could improve about this class inside the callback, not just in terms of speed, but also structure.

Clearly there is some overhead in havingIm especially concerned with the way I get around the fact that GLFW callbacks are static. In my callbacks I want to retriveacces methods in my class and so I create a pointer to the actual instance everytime a button is pressed'window user' using glfwGetWindowUserPointer, to acces the actual class methods an member variables.

Still i'm just looking for any thought on how to improve this code.

Links to so my question is, would you consider this an optimal solution?GLFW and STB .

Im creating a window class in C++ to provide a bit of abstraction for a GLFW window. To me it makes sense to add a key_callback as a method in my class. The issue is ofcourse that GLFW is written in C, and so it requires callbacks to be static.

I found that GLFW has a glfwSetWindowUserPointer function that sets:

.. sets the user-defined pointer of the specified window.. ----- Docs

So I went with the following solution:

In my window.h:

class Window {
 GLFWwindow* window;
 // More members..
 
public:
 Window(...); // Constructor
private:
 // Stuff...
 void setKeyCallback(); // Function to set keycallback
 static void static_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // The static keycallback
 void keyCallback(int key, int scancode, int action, int mods); // Non static keycallback
};

In my window.cpp:

Window::Window(...) {
 glfwSetWindowUserPointer(window, this);
 setKeyCallback();
 // more stuff
}
void Window::setKeyCallback() {
 glfwSetKeyCallback(window, static_KeyCallback); // Set keycallback to static member function
}
void Window::static_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
 Window* actualWindow = (Window*) glfwGetWindowUserPointer(window); // Get a pointer to the window instance that has the actual window.
 actualWindow->keyCallback(key, scancode, action, mods); // Acces that actual window instanceses method
}
void Window::keyCallback(int key, int scancode, int action, int mods) {
 // Do stuff..
}

The primary reason that I need(or would like) the callback to be nonstatic is because I want to use methods from the Window class inside the callback.

Clearly there is some overhead in having to retrive a pointer to the actual instance everytime a button is pressed, so my question is, would you consider this an optimal solution?

Im creating a window class in C++ to provide a bit of abstraction for a GLFW window.

window.h

#pragma once
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
class Window {
 GLFWwindow* m_Window;
 GLFWmonitor* m_Monitor;
  const char* m_Title;
 GLFWimage m_Icon[1];
 int m_Width, m_Height;
 int m_PosX, m_PosY;
  bool m_Fullscreen;

public:
 Window(int width, int height, const char* title, const char* iconPath);  ~Window();
 GLFWwindow* getWindow();
 const char** getRequiredExtensions();
private:
 void queryVulkanSupport();
 void initGLFW(); void createWindow();
 void setIcon(const char* path);
 void center();
 void setFullscreen();
 void setWindowSizeCallback();
 static void static_WindowSizeCallback(GLFWwindow* window, int width, int height);
  void windowSizeCallback(int width, int height); void setKeyCallback();
 static void static_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); void keyCallback(int key, int scancode, int action, int mods);
};

window.cpp

#include "window.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#include <stdexcept>
#include <string>
Window::Window(int width, int height, const char* title, const char* iconPath) : m_Fullscreen(false), m_Width(width), m_Height(height), m_Title(title) {
 initGLFW();
  queryVulkanSupport();
 m_Monitor = glfwGetPrimaryMonitor();
 createWindow();
 setIcon(iconPath);
 setWindowSizeCallback();
 setKeyCallback();
}

Window::~Window() {
 glfwDestroyWindow(m_Window);
  glfwTerminate();
}
GLFWwindow* Window::getWindow() {
 return m_Window;
}
const char** Window::getRequiredExtensions()
{
 uint32_t count;
 const char** extensions = glfwGetRequiredInstanceExtensions(&count);
 return extensions;
}
void Window::queryVulkanSupport() {
 if (!glfwVulkanSupported()) {
 throw std::runtime_error("Vulkan not supported!");
 }
}
void Window::initGLFW() {
 if (!glfwInit()) {
 throw std::runtime_error("Failed to initialize GLFW!");
 }
}
void Window::createWindow() {
 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
 m_Window = glfwCreateWindow(m_Width, m_Height, m_Title, nullptr, nullptr);
 if (!m_Window) {
 throw std::runtime_error("Could not create GLFW window!");
 }
 glfwSetWindowUserPointer(m_Window, this);  center();
}
void Window::setIcon(const char* path) {
 m_Icon[0].pixels = stbi_load(path, &m_Icon[0].width, &m_Icon[0].height, 0, 4);
 if (m_Icon[0].pixels)
 glfwSetWindowIcon(m_Window, 1, m_Icon);
}
void Window::center() {
 const GLFWvidmode* vidMode = glfwGetVideoMode(m_Monitor);
 glfwSetWindowPos(m_Window, (vidMode->width - m_Width) / 2, (vidMode->height - m_Height) / 2);
}
void Window::setFullscreen() {
 if (!m_Fullscreen) {
 const GLFWvidmode* vidMode = glfwGetVideoMode(m_Monitor);
 glfwGetWindowPos(m_Window, &m_PosX, &m_PosY);
 glfwGetWindowSize(m_Window, &m_Width, &m_Height);
 glfwSetWindowMonitor(m_Window, m_Monitor, 0, 0, vidMode->width, vidMode->height, vidMode->refreshRate);
 glfwSetWindowSize(m_Window, vidMode->width, vidMode->height);
 m_Fullscreen = !m_Fullscreen;
 }
 else {
 glfwSetWindowMonitor(m_Window, nullptr, m_PosX, m_PosY, m_Width, m_Height, 0);
 glfwSetWindowSize(m_Window, m_Width, m_Height);
 m_Fullscreen = !m_Fullscreen;
 }
}
void Window::setWindowSizeCallback() {
 glfwSetWindowSizeCallback(m_Window, static_WindowSizeCallback);
}
void Window::static_WindowSizeCallback(GLFWwindow* window, int width, int height) {
 Window* actualWindow = (Window*) glfwGetWindowUserPointer(window); actualWindow->windowSizeCallback(width, height);
}
void Window::windowSizeCallback(int width, int height) {
  glfwSetWindowSize(m_Window, width, height);
}
void Window::setKeyCallback() {
 glfwSetKeyCallback(m_Window, static_KeyCallback);
}
void Window::static_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
  Window* actualWindow = (Window*) glfwGetWindowUserPointer(window);
  actualWindow->keyCallback(key, scancode, action, mods);
}
void Window::keyCallback(int key, int scancode, int action, int mods) {
 if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
 glfwSetWindowShouldClose(m_Window, true);
 if (key == GLFW_KEY_F11 && action == GLFW_RELEASE)
 setFullscreen();
}

main.cpp

#include "window.h"
int main() {
 Window window(600, 300, "Vulkan engine!", "include/Ressources/VulkanIcon.png");
  while (!glfwWindowShouldClose(window.getWindow())) {
 glfwPollEvents();
 }
}

The code works as intended. Im really new to c++ tho and I assume there is tons i could improve about this class, not just in terms of speed, but also structure.

Im especially concerned with the way I get around the fact that GLFW callbacks are static. In my callbacks I want to acces methods in my class and so I create a pointer to the actual 'window user' using glfwGetWindowUserPointer, to acces the actual class methods an member variables.

Still i'm just looking for any thought on how to improve this code.

Links to GLFW and STB .

Post Closed as "Not suitable for this site" by vnp, Jamal
Source Link
Cortex
  • 440
  • 3
  • 16
Loading
lang-cpp

AltStyle によって変換されたページ (->オリジナル) /