Function pointer compatibility rules for Parameters and Tuples

(may this question find you in good faith)

I have found myself in a situation where the ability to do this…

fn fun(a:u8, b:u8, c:u8, d:u8) void {
    std.debug.print("{} {} {} {}", .{a, b, c, d});
}
pub fn main() void {
   const fptr: *const fn (struct {u8,u8,u8,u8}) void = @ptrCast(&fun);
   fptr(.{33, 33, 33, 33});
}

…would really come in handy (now it prints some nonsense).

Is there a way to convert a function that takes a bunch of args to a function that takes a struct of them?

I think you messed up the types. The following code works as expected:

const std = @import("std");
fn fun(a:u8, b:u8, c:u8, d:u8) void {
    std.debug.print("{} {} {} {}\n", .{a, b, c, d});
}
pub fn main() void {
   const fptr = &fun;
   fptr(33, 33, 33, 33);
}

Normal structs and tuples do not have a defined memory layout. This might be possible with extern or packed structs, but I think that would still be in the unsafe territory.

But if you want to call a function with a parameter tuple you can do this instead:

@call(.auto, fun, .{33, 33, 33, 33});
9 Likes