user11686059
user11686059

Reputation:

Expected type ?extern fn

I don't know any C or Zig. But I'm trying some stuff out and I'm really impressed so far. I'm trying to run a web server in Zig using a C library "lwan". It works. But I'm having some trouble with making my handler function.

/mnt/c/www/zig/hello/main.zig:35:56: error: expected type '?extern fn([*c].cimport:4:14.struct_lwan_request, [*c].cimport:4:14.struct_lwan_response, ?*c_void) .cimport:4:14.enum_lwan_http_status', found '*const fn([*c].cimport:4:14.struct_lwan_request, [*c].cimport:4:14.struct_lwan_response, ?*c_void) .cimport:4:14.enum_lwan_http_status'
        lwan.lwan_url_map{ .prefix = c"/", .handler = &hello_world },
                                                       ^
/mnt/c/www/zig/hello/main.zig:35:56: note: pointer type child 'fn([*c].cimport:4:14.struct_lwan_request, [*c].cimport:4:14.struct_lwan_response, ?*c_void) .cimport:4:14.enum_lwan_http_status' cannot cast into pointer type child '.cimport:4:14.enum_lwan_http_status'
        lwan.lwan_url_map{ .prefix = c"/", .handler = &hello_world },
                                                       ^
zig-cache/o/7Ejdc3DFhsEkPBHu2o3vlPoREApH2LmQtGmS7KyNIBhIeaHdzX6DwQhyzd5U7Eo0/cimport.zig:1234:35: note: .cimport:4:14.enum_lwan_http_status declared here
pub const enum_lwan_http_status = extern enum {

So I'm guessing the type of my handler function is wrong. This is my handler:

fn hello_world(req: [*c]lwan.struct_lwan_request, res: [*c]lwan.struct_lwan_response, data: ?*c_void) lwan.enum_lwan_http_status {
    return lwan.enum_lwan_http_status.HTTP_OK;
}

How do I change it to the type "?extern fn"?

I'm not even sure I'm doing something I'm supposed to do. If this isn't the purpose of Zig, just let me know.

One more thing: lwan creates handlers using this code:

#define LWAN_HANDLER_DECLARE(name_)                                            \
    static enum lwan_http_status lwan_handler_##name_(                         \
        struct lwan_request *, struct lwan_response *, void *)

#define LWAN_HANDLER_DEFINE(name_)                                             \
    static const struct lwan_handler_info                                      \
        __attribute__((used, section(LWAN_SECTION_NAME(lwan_handler))))        \
            lwan_handler_info_##name_ = {.name = #name_,                       \
                                         .handler = lwan_handler_##name_};     \
    static enum lwan_http_status lwan_handler_##name_(                         \
        struct lwan_request *request __attribute__((unused)),                  \
        struct lwan_response *response __attribute__((unused)),                \
        void *data __attribute__((unused)))

#define LWAN_HANDLER(name_)                                                    \
    LWAN_HANDLER_DECLARE(name_);                                               \
    LWAN_HANDLER_DEFINE(name_)

And then uses this to pass the handler:

#define LWAN_HANDLER_REF(name_) lwan_handler_##name_

Upvotes: 1

Views: 912

Answers (1)

andrewrk
andrewrk

Reputation: 31182

You need to make your handler function have the C calling convention by adding the word extern in front of it:

extern fn hello_world(req: [*c]lwan.struct_lwan_request, res: [*c]lwan.struct_lwan_response, data: ?*c_void) lwan.enum_lwan_http_status {
    return lwan.enum_lwan_http_status.HTTP_OK;
}

See also this related issue, which may help clarify the syntax: https://github.com/ziglang/zig/issues/661

Upvotes: 3

Related Questions