Using C string in Wasm - function signature mismatch

I am a newbie and am trying to use zig to compile c to wasm. I am having problems passing strings from C to Zig. You can view my toy project

When I compile I get the following:

zig build-lib test Debug wasm32-freestanding: error: warning(link): unexpected LLD stderr:

wasm-ld: warning: function signature mismatch: c_string

defined as (i32) -> i32 in /home/gap/temp/zig_wasm/zig-cache/o/12a4e7a2145498c3a4aa83fe910529d8/test.wasm.o

>>> defined as () -> i32 in /home/gap/temp/zig_wasm/zig-cache/o/085d0386b639fd727f0fd20ecbeb50cc/bindings.o

When I run using wasmtime zig-out/lib/test.wasm --invoke string_from_zig I get:

Error: failed to run main module `zig-out/lib/test.wasm`

Caused by:
    0: failed to invoke `string_from_c`
    1: error while executing at wasm backtrace:
           0:   0x8f - <unknown>!signature_mismatch:c_string
           1:  0x23b - <unknown>!string_from_c
       note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
    2: wasm trap: wasm `unreachable` instruction executed

My C code is

const char *c_string() {
    return "Hello from c";
}

My Zig code is:

const c = @cImport({
    @cInclude("bindings.h");
});

export fn string_from_c() [*:0]const u8 {
    const buffer: [*c]const u8 = c.c_string();
    return buffer;
}

I am getting the same warning using the latest zig master, but the invoke works displaying an i32 instead of a string.

❯ zig build-exe src/main.zig src/bindings.c -lc -I src -target wasm32-freestanding -fno-entry --export=string_from_zig
LLD Link... warning(link): unexpected LLD stderr:
wasm-ld: warning: function signature mismatch: c_string
>>> defined as (i32) -> i32 in main.wasm.o
>>> defined as () -> i32 in /home/din/zig-wasm-problem/zig-cache/o/ff939e02b78237a79bc6054f768dc943/bindings.o

❯ wasmtime main.wasm --invoke string_from_zig
warning: this CLI invocation of Wasmtime will be parsed differently in future
         Wasmtime versions -- see this online issue for more information:
         https://github.com/bytecodealliance/wasmtime/issues/7384

         Wasmtime will now execute with the old (<= Wasmtime 13) CLI parsing,
         however this behavior can also be temporarily configured with an
         environment variable:

         - WASMTIME_NEW_CLI=0 to indicate old semantics are desired and silence this warning, or
         - WASMTIME_NEW_CLI=1 to indicate new semantics are desired and use the latest behavior
warning: using `--invoke` with a function that returns values is experimental and may break in the future
1048576

This sounds promising. What change to the code did you make? How can I replicate it?

There are no changes in the code. I used the latest 0.12.0-dev without build.zig

There are some differences in build.zig between 0.11.0 and 0.12.0:

  • You must add an Executable instead of SharedLibrary.
  • There are some build api changes:
+const target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding});
-    .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
+    .target = target,

Also see the web assembly documentation: Documentation - The Zig Programming Language

1 Like