C-code callbacks in extern struct

new to zig and looking to interop with an existing c-lang project
the c-code is passing a struct with pointers to a number of callbacks

const OutputProtocol = extern struct {
  reset: *fn (self: *OutputProtocol, extended: bool) u64,
  output_string: *fn (self: *OutputProtocol, string: *u8) u64,
}

export fn main(output: OutputProtocol) callconv(.C) u64 {
    // and I want to be able to call the function:
    output.output_string(output, "testing\x00");
    return 0;
}

but it gives me this error error: expected function, found '*fn (self: *OutputProtocol, string: *u8) u64

that’s a simplified example, any help would be amazing as I’ve been hacking around on this for hours

1 Like

Remove the * from *fn

it won’t let me as the struct is extern
error: extern structs cannot contain fields of type 'fn (self: *OutputProtocol, string: *u8) u64'

Not a very good error message, it doesn’t say what’s wrong with the function pointer type, just that it doesn’t work with extern. Add callconv(.C) to your function pointers. Also string should probably be [*:0]const u8. Here’s your full example with fixes so it will compile and test. Run it with “zig test this_example.zig”:

const OutputProtocol = extern struct {
  reset: fn (self: *OutputProtocol, extended: bool) callconv(.C) u64,
  output_string: fn (self: *OutputProtocol, string: [*:0]const u8) callconv(.C) u64,
};

export fn main(output: *OutputProtocol) callconv(.C) u64 {
    // and I want to be able to call the function:
    _ = output.output_string(output, "testing\x00");
    return 0;
}



const std = @import("std");
fn testOutputString(self: *OutputProtocol, string: [*:0]const u8) callconv(.C) u64 {
    _ = self;
    std.log.debug("got string '{s}'", .{std.mem.spanZ(string)});
    return 0;
}
test {
    var op = OutputProtocol {
        .reset = undefined,
        .output_string = testOutputString,
    };
    _ = main(&op);
}
2 Likes

Thanks! This works and you are right about the [*:0]const u8 too
loving to language - really jumping into the deep end with this project though

3 Likes