I'm currently refactoring my code into a class (VkAPP
), and stumbled upon this error:
argument of type "void (VkAPP::)(GLFWwindow window, int width, int height)" is incompatible with parameter of type "GLFWwindowsizefun"
Here is the function in question:
void onWindowResized(GLFWwindow* window, int width, int height) {
VkSurfaceCapabilitiesKHR surfaceCapabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevices[0], surface, &surfaceCapabilities);
if (width > surfaceCapabilities.maxImageExtent.width) width = surfaceCapabilities.maxImageExtent.width;
if (height > surfaceCapabilities.maxImageExtent.height) height = surfaceCapabilities.maxImageExtent.height;
if (width == 0 || height == 0) return;
WIDTH = width;
HEIGHT = height;
recreateSwapchain();
}
Here is the call:
glfwSetWindowSizeCallback(window, onWindowResized);
The funtion and the call are in the same class.
If I turn this into:
static void onWindowResized
I get:
a nonstatic member reference must be relative to a specific object
for physicalDevices[0]
, surface
, WIDTH
, HEIGHT
, and recreateSwapchain()
Let's start with the first error message you get.
The GLFWwindowsizefun
is defined like this:
typedef void(* GLFWwindowsizefun) (GLFWwindow *window, int width, int height)
On the other hand, the (non static) onWindowResized
method of your C++ class has an implicit class instance pointer.
In other words, your VkAPP
C++ class' non-static onWindowResized
method declared like this:
// Inside VkAPP class
void onWindowResized(GLFWwindow* window, int width, int height)
has an implicit parameter that is a pointer to the VkAPP
class instance (i.e. the classic this
pointer in C++):
void VkAPP::onWindowResized(VkAPP* this, /* implicit VkAPP* 'this' pointer */ ,
GLFWwindow* window,
int width,
int height)
So, the C++ compiler signaled to you the mismatch between the expected GLFWwindowsizefun
(which doesn't have the implicit this
pointer), and your VkAPP::onWindowResized
method (which does have the implicit this
pointer).
How can you resolve this mismatch?
Well, you can define a static method in your VkAPP
C++ class, like this:
// Inside VkAPP class
//
// Note: the method is *static*
static void onWindowResizedStatic(GLFWwindow* window, int width, int height)
Note that static
methods do not have the implicit this
pointer, so the above method corresponds to the GLFWwindowsizefun
typedef
.
So you can pass it to the glfwSetWindowSizeCallback
function call:
// You had this line, which didn't work as onWindowResized was not static:
//
// glfwSetWindowSizeCallback(window, onWindowResized); <<-- error
//
// Pass a *static* method as callback, instead:
//
glfwSetWindowSizeCallback(window, onWindowResizedStatic);
Unfortunately, as the other error message you got revealed, you cannot access instance-specific data members like physicalDevices[0]
, surface
, WIDTH
, HEIGHT
, etc., from a static method of your class.
So, the idea here is to use the static
method as a place to just forward the call to the instance-specific method of your class, e.g.:
// Inside VkAPP class
static void onWindowResizedStatic(GLFWwindow* window, int width, int height) {
// Somehow get the instance-specific "this" pointer
VkAPP* pThis = ... /* we'll see that later */;
// Forward the call to the non-static method callback:
pThis->onWindowResized(window, width, height);
}
Now, how can you retrieve the this
pointer from the static
method above?
Well, during initialization (e.g. in the constructor of your C++ class, or in another initialization method), once you have a valid GLFWwindow
object (for example, created with glfwCreateWindow
), you can invoke the glfwSetWindowUserPointer
function to set the instance-specific this
pointer as the generic "user pointer" associated to the window object:
// Inside a method of your VkAPP C++ class, during initialization:
// Set the "this" pointer as window's user pointer for later retrieval
glfwSetWindowUserPointer(window, this);
Then, the this
pointer can be later retrieved invoking the symmetric glfwGetWindowUserPointer
:
// Inside VkAPP class
static void onWindowResizedStatic(GLFWwindow* window, int width, int height) {
// Get the instance-specific "this" pointer
// that was set before during initialization
VkAPP* pThis = static_cast<VkAPP*>(glfwGetWindowUserPointer(window));
// Forward the call to the non-static method callback:
pThis->onWindowResized(window, width, height);
}
Note that, since your onWindowResized
method is not static, you can use all the instance-specific data members like physicalDevices[0]
, surface
, etc., or invoke other member functions like recreateSwapchain()
, that your second error message was complaining about.