1

For some reason I need to translate a piece of C code to Rust with c2rust and then compile it to wasm. The Rust code is as follows:

extern "C" {
    fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
    fn time(__timer: *mut time_t) -> time_t;
    fn ctime(__timer: *const time_t) -> *mut libc::c_char;
    fn memcpy(
        _: *mut libc::c_void,
        _: *const libc::c_void,
        _: libc::c_ulong,
    ) -> *mut libc::c_void;
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
}
pub type __time_t = libc::c_long;
pub type time_t = __time_t;
unsafe fn main_0() -> libc::c_int {
    let mut src: [libc::c_char; 14] = *::core::mem::transmute::<
        &[u8; 14],
        &mut [libc::c_char; 14],
    >(b"Hello, world!\0");
    let mut dest: [libc::c_char; 20] = [0; 20];
    memcpy(
        dest.as_mut_ptr() as *mut libc::c_void,
        src.as_mut_ptr() as *const libc::c_void,
        (strlen(src.as_mut_ptr())).wrapping_add(1 as libc::c_int as libc::c_ulong),
    );
    printf(b"src: %s\n\0" as *const u8 as *const libc::c_char, src.as_mut_ptr());
    printf(b"dest: %s\n\0" as *const u8 as *const libc::c_char, dest.as_mut_ptr());
    let mut cur_time: time_t = 0;
    time(&mut cur_time);
    printf(
        b"Current local time: %s\0" as *const u8 as *const libc::c_char,
        ctime(&mut cur_time),
    );
    return 0 as libc::c_int;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

then I run:

cargo build --target=wasm32-wasi

Then the linker reported a function signature mismatch error:

  = note: rust-lld: error: function signature mismatch: time
          >>> defined as (i32) -> i32 in /home/ubuntu/demo/demo_rust/target/wasm32-wasi/debug/deps/main-975cb877ac86c0d4.3vi6reg7dgepzj1h.rcgu.o
          >>> defined as (i32) -> i64 in /home/ubuntu/.rustup/toolchains/nightly-2022-08-08-x86_64-unknown-linux-gnu/lib/rustlib/wasm32-wasi/lib/self-contained/libc.a(time.o)
          

Is this caused by an inconsistency between wasm's libc and Rust's libc, is there a way to make it work?

Effy
  • 11
  • 2
  • How about changing `pub type __time_t = libc::c_long;` to `pub type __time_t = libc::c_longlong;`? – prog-fh Jun 16 '23 at 10:02
  • it works! This is weird because both libc::c_long and libc::c_longlong are i64. – Effy Jun 17 '23 at 06:50
  • When looking at [the documentation of `libc::c_long`](https://docs.rs/libc/0.2.146/libc/type.c_long.html) and clicking on **source**, the path shows that the documentation was generated for `x86_64` (`c_long` and `c_longlong` are both `i64`). But when looking at [the `libc` repository](https://github.com/rust-lang/libc), the file `src/wasi.rs` shows different sizes for `c_long` and `c_longlong`. That's normal since this crate tends to mimic the C system API, and in C the primitive types can vary in size according to the platform. – prog-fh Jun 17 '23 at 07:15
  • However, in `src/wasi.rs`, `time_t` is supposed to be a `c_longlong` and I don't know why your generated code supposed it was a `c_long`. – prog-fh Jun 17 '23 at 07:17

0 Answers0