C function pointers cast error

I’m following the Vulkan tutorial in Zig but got stuck when calling vkGetInstanceProcAddr.
This is my wrapper around the function:

fn CreateDebugUtilsMessengerEXT(
    pCreateInfo: *const c.VkDebugUtilsMessengerCreateInfoEXT,
    pAllocator: ?*const c.VkAllocationCallbacks,
    pMessenger: *c.VkDebugUtilsMessengerEXT,
) c.VkResult {
    const func: c.PFN_vkCreateDebugUtilsMessengerEXT = @as(c.PFN_vkCreateDebugUtilsMessengerEXT, c.vkGetInstanceProcAddr(
        g_vulkan_context.instance,
        "vkCreateDebugUtilsMessengerEXT",
    )) orelse return c.VK_ERROR_EXTENSION_NOT_PRESENT;

    return func(g_vulkan_context.instance, pCreateInfo, pAllocator, pMessenger);
}

and produces the following error:

error: expected type '?*const fn (?*cimport.struct_VkInstance_T, [*c]const cimport.struct_VkDebugUtilsMessengerCreateInfoEXT, [*c]const cimport.struct_VkAllocationCallbacks, [*c]?*cimport.struct_VkDebugUtilsMessengerEXT_T) callconv(.C) c_int', found '?*const fn () callconv(.C) void'
    const func: c.PFN_vkCreateDebugUtilsMessengerEXT = @as(c.PFN_vkCreateDebugUtilsMessengerEXT, c.vkGetInstanceProcAddr(

I kind of have an idea what it means but I’ve tried a couple of things and I have no idea how to fix it.

Thanks :slight_smile:

Try using @ptrCast. @as is used for coercions, meaning safe conversions to less specific types. The function pointer type you are trying to convert to is more specific than the return type of vkGetInstanceProcAddress, so you have to use @ptrCast.

1 Like

I already tried it, but apparently error: @ptrCast must have a known result type. Which I don’t know why it says that because I explicitly say that the type should be c.PFN_vkCreateDebugUtilsMessengerEXT.

Is this the line of code the gives you that error?

const func: c.PFN_vkCreateDebugUtilsMessengerEXT = @ptrCast(c.vkGetInstanceProcAddr(
        g_vulkan_context.instance,
        "vkCreateDebugUtilsMessengerEXT",
    ));

Yeah, plus this after the call: orelse return c.VK_ERROR_EXTENSION_NOT_PRESENT;

EDIT: I’ve removed this part and the error changed, so we are going someplace.

error: cannot call optional type '?*const fn (?*cimport.struct_VkInstance_T, [*c]const cimport.struct_VkDebugUtilsMessengerCreateInfoEXT, [*c]const cimport.struct_VkAllocationCallbacks, [*c]?*cimport.struct_VkDebugUtilsMessengerEXT_T) callconv(.C) c_int'

You need to unpack the optional first - you have an optional(*function).

You can directly unpack it with foo.? to get your function pointer or use payload capture to unpack it if (foo) |bar| // use bar .

1 Like

try this:

const func: c.PFN_vkCreateDebugUtilsMessengerEXT = 
    @as(?c.PFN_vkCreateDebugUtilsMessengerEXT,
       @ptrCast(c.vkGetInstanceProcAddr(
            g_vulkan_context.instance,
            "vkCreateDebugUtilsMessengerEXT",
    ))) orelse return c.VK_ERROR_EXTENSION_NOT_PRESENT;
const func = @as(
    c.PFN_vkCreateDebugUtilsMessengerEXT,
    @ptrCast(c.vkGetInstanceProcAddr(
        g_vulkan_context.instance,
        "vkCreateDebugUtilsMessengerEXT",
    ),
) orelse return c.VK_ERROR_EXTENSION_NOT_PRESENT;

is probably the most concise version. vkGetInstanceProcAddr already returns an optional pointer.