You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译含libc依赖的Rust项目到Wasm时遇函数签名不匹配问题求助

解决c2rust转换代码编译WASM时的libc函数签名不匹配问题

问题场景

用c2rust将C代码转换为Rust后,执行cargo build --target=wasm32-wasi编译时,链接器抛出函数签名不匹配错误,相关代码和错误信息如下:

转换后的Rust代码

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) }
}

编译错误信息

= 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)

怀疑是Wasm的libc与Rust的libc不一致导致,求可行解决办法。

解决办法

  • 直接复用libc crate的标准定义
    c2rust生成的代码手动声明了time_t和C函数,这和libc crate针对wasm32-wasi目标的内置定义冲突。修改代码,移除手动声明的类型和函数,直接引用libc的导出:

    use libc::{c_char, c_int, c_ulong, c_void, time_t, printf, time, ctime, memcpy, strlen};
    
    unsafe fn main_0() -> c_int {
        let mut src: [c_char; 14] = *::core::mem::transmute::<
            &[u8; 14],
            &mut [c_char; 14],
        >(b"Hello, world!\0");
        let mut dest: [c_char; 20] = [0; 20];
        memcpy(
            dest.as_mut_ptr() as *mut c_void,
            src.as_mut_ptr() as *const c_void,
            (strlen(src.as_mut_ptr())).wrapping_add(1 as c_int as c_ulong),
        );
        printf(b"src: %s\n\0" as *const u8 as *const c_char, src.as_mut_ptr());
        printf(b"dest: %s\n\0" as *const u8 as *const 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 c_char,
            ctime(&cur_time),
        );
        return 0 as c_int;
    }
    pub fn main() {
        unsafe { ::std::process::exit(main_0() as i32) }
    }
    
  • 避免手动定义libc相关类型
    wasm32-wasi目标下,libc crate已经适配了WASI的libc实现,不要自行定义__time_t、time_t这类和系统libc强相关的类型,防止和目标平台实际定义不匹配。

  • 优化c2rust转换参数
    后续用c2rust转换时,添加--extern-libc参数,让生成的代码直接依赖libc crate的类型定义,减少手动适配的工作量。

  • 升级工具链版本
    你使用的是2022年的nightly版本,较旧的工具链可能存在WASI目标的libc适配缺陷。可以升级到最新的稳定版或nightly版,确保工具链对WASI的支持更完善。

内容的提问来源于stack exchange,提问作者Effy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 04:34:52