如何在Rust中调用预编译C静态库(.lib)中的函数
Rust 直接链接预编译 .lib 静态库解决方案
1 修正 build.rs 配置
不要使用相对路径,通过 Cargo 内置的环境变量拼接绝对路径避免寻址错误,链接库只需要指定纯库名,不需要路径、前缀、后缀:
fn main() { // CARGO_MANIFEST_DIR 是当前项目 Cargo.toml 所在的根目录 let lib_path = format!("{}/my_c_project/cmake-build-debug", env!("CARGO_MANIFEST_DIR")); println!("cargo:rustc-link-search={}", lib_path); // MSVC 编译的静态库不需要加 lib 前缀,直接写原始库名即可 println!("cargo:rustc-link-lib=static=my_c_project"); }
同时把你之前重命名的 libmy_c_project.lib 改回原来的 my_c_project.lib,lib 前缀是 Linux/macOS/MinGW 平台的静态库命名规则,MSVC 平台不需要。
2 修正 main.rs 的 extern 块声明
必须显式指定 extern "C",否则 Rust 会默认使用 Rust 调用约定查找符号,出现符号名不匹配的问题,不需要额外加 #[link] 指令,build.rs 已经处理了链接配置:
extern "C" { fn hello(); } fn main() { unsafe { hello(); } }
3 确认工具链与库架构匹配
- 如果你编译 .lib 用的是 MSVC 工具链,Rust 也要使用对应的 MSVC 工具链(比如
stable-x86_64-pc-windows-msvc),不能使用 GNU 工具链,二者的静态库格式不兼容。 - 确认编译 .lib 的架构和 Rust 工具链架构一致,比如都是 64 位或者都是 32 位,架构不同也会出现找不到符号的问题。
4 常见问题说明
- 注释掉
hello()调用就能编译的原因:Rust 链接器默认会裁剪未使用的符号,没有调用hello的时候,链接器根本不会去查找这个符号,自然不会报错,不是链接逻辑没有执行。 - build.rs 里
cargo:开头的打印是给 Cargo 传递配置指令,只要语法没错就不会抛出错误,参数错误只会在链接阶段才会暴露。 - 不要同时使用 build.rs 链接配置和
#[link]指令,二者选其一即可,优先使用 build.rs 的方式,后续修改配置更灵活。
排查手段
如果按照上面的步骤还是报找不到符号,可以用 VS 自带的 dumpbin 工具查看 .lib 的导出符号:dumpbin /symbols my_c_project.lib
在输出中查找 hello 函数是否存在,确认 C 代码编译的时候没有被优化掉,确实导出了对应符号。
内容的提问来源于stack exchange,提问作者Plegeus
相关产品推荐
相关产品推荐

