我已经开始使用 Vulkan,并且刚刚完成了验证层。 在这里,他们将静态函数
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(...)
添加到.cpp文件中,然后简单地赋值
createInfo.pfnUserCallback = debugCallback;
这是如何(/为什么)工作的?我当然知道回调,但我试图将此函数添加到我的渲染器类中,而不仅仅是在 .cpp 文件中的“本地”(?),首先是在头文件中:
VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
void* pUserData);
然后在.cpp文件中:
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanRenderer::DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
void* pUserData)
{
//...
}
最后像这样使用分配它:
createInfo.pfnUserCallback = &VulkanRenderer::DebugCallback;
我的版本实际上不起作用,所以我可能在这里想错了。但我不知道他们在教程中做了什么,甚至不知道要搜索什么才能理解这一点。
我确实知道要编写什么代码才能使它像他们拥有的那样工作,我只是不知道为什么。
当
DebugCallback
为非静态成员函数时,则&VulkanRenderer::DebugCallback
为成员函数指针。
成员函数指针不是函数指针,但是
pfnUserCallback
想要一个函数指针。
成员函数指针和函数指针不能一样工作,因为非静态成员函数需要知道在哪个对象上调用它,而自由函数则不是这样。
现在,Vulkan 是一个 C API,而不是 C++ API,因此它根本不知道成员函数,并且还使用 C 惯用法来实现回调接口而不是 C++ 接口。
然而,C 惯用语仍然允许传递有关要调用成员函数的对象的信息。这就是
pUserData
的用途。它将原封不动地传递给您的回调,并且回调可以将其用于例如做一个成员函数调用:
createInfo.pUserData = this;
createInfo.pfnUserCallback = [](auto a, auto b, auto c, void* pUserData){ return static_cast<VulkanRenderer*>(pUserData)->DebugCallback(a, b, c); };
(我偷懒了模板参数,你当然可以给它们正确的类型和名称,但编译器也可以推导出它们。)
或者,如果
DebugCallback
不需要是非静态的,你当然也可以将它声明为static
成员函数。那么你的方法也会奏效。静态成员函数不需要关于调用它的对象的任何附加信息,因此形成像自由函数一样的普通函数指针。