zig icon indicating copy to clipboard operation
zig copied to clipboard

return type '?*const fn () callconv(.C) void' cannot cast into return type '?*anyopaque'

Open Xyndra opened this issue 8 months ago • 3 comments

Zig Version

0.12.0-dev.1828+225fe6ddb

Steps to Reproduce and Observed Behavior

I am trying to link GLFW and GLAD. related headers in GLAD:

typedef void* (* GLADloadproc)(const char *name);
int gladLoadGLLoader(GLADloadproc);

This is my wished C code:

if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))

My current zig code:

const c_cast = @import("std").zig.c_translation.cast;
if (c.gladLoadGLLoader(c_cast(c.GLADloadproc,  c.glfwGetProcAddress)) == c.GL_FALSE)

This is the understanding from zls:

pub const GLADloadproc = ?*const fn ([*c]const u8) callconv(.C) ?*anyopaque;
pub extern fn gladLoadGLLoader(GLADloadproc) c_int;
pub const GLFWglproc = ?*const fn () callconv(.C) void;
pub extern fn glfwGetProcAddress(procname: [*c]const u8) GLFWglproc;

This is the error:

[zig]\lib\std\zig\c_translation.zig:98:26: error: expected type '*const fn ([*c]const u8) callconv(.C) ?*anyopaque', found '*const fn ([*c]const u8) callconv(.C) ?*const fn () callconv(.C) void'
    return @as(DestType, target);
                         ^~~~~~
[zig]\lib\std\zig\c_translation.zig:98:26: note: pointer type child 'fn ([*c]const u8) callconv(.C) ?*const fn () callconv(.C) void' cannot cast into pointer type child 'fn ([*c]const u8) callconv(.C) ?*anyopaque'
[zig]\lib\std\zig\c_translation.zig:98:26: note: return type '?*const fn () callconv(.C) void' cannot cast into return type '?*anyopaque'
[zig]\lib\std\zig\c_translation.zig:98:26: note: cast discards const qualifier

Expected Behavior

it working

Xyndra avatar Dec 19 '23 10:12 Xyndra

Yes but it works in C: https://learnopengl.com/Getting-started/Hello-Window

Xyndra avatar Dec 19 '23 11:12 Xyndra

This looks like an oversight in c_cast where function bodies (fn () void) are not coerced to function pointers (*const fn () void).

In the meantime, you can fix the issue by either adding a & before the function name to explicitly take a pointer to it

 const c_cast = @import("std").zig.c_translation.cast;
-if (c.gladLoadGLLoader(c_cast(c.GLADloadproc,  c.glfwGetProcAddress)) == c.GL_FALSE)
+if (c.gladLoadGLLoader(c_cast(c.GLADloadproc,  &c.glfwGetProcAddress)) == c.GL_FALSE)

or by using @ptrCast

 const c_cast = @import("std").zig.c_translation.cast;
-if (c.gladLoadGLLoader(c_cast(c.GLADloadproc,  c.glfwGetProcAddress)) == c.GL_FALSE)
+if (c.gladLoadGLLoader(@ptrCast(&c.glfwGetProcAddress)) == c.GL_FALSE)

@ptrCast is probably the way to go if you're writing original code in Zig. Functions in c_translation are mainly meant for automatically translated code.

castholm avatar Dec 19 '23 14:12 castholm

thanks :)

Xyndra avatar Dec 19 '23 16:12 Xyndra