博主最近从新学习 Rust FFI 的使用,但是手头上没有可用的 Linux 环境(Windows 编译c太麻烦了),于是就尝试着使用
WSL来搭建 Rust 环境和简易的 c 编译环境,并记录下中间遇到的一些坑。感谢 Unsafe Rust 群群友 @框框
对本文的首发赞助!感谢 Rust
深水群 @栗子 的 gcc 指导!阅读须知
- 如何解决 WSL 中文乱码问题?
顺带一提的是,博主通过 VS Code 使用 WSL,因为 Win 10 已经配置成 UTF-8 编码,所以并没有出现乱码问题
WSL Rust 环境搭建
由于 WSL 是新装的,没有 Rust 和 gcc/g++ 环境,因此需要安装:但是由于在国内访问 Rust 官方网站会很慢,因此设置镜像到 Windows 环境变量中:然后,使用 WSLENV环境变量将上述变量共享到 WSL 中:然后重启 WSL 终端,重新执行 Rust 一键脚本。以下两个项目均来自 《Rust编程之道》一书,源代码仓库在这里Rust 调用 C/C++
Rust 调用 C/C++ 代码可以使用 cc crate 配合 build.rs 预先编译好 C/C++ 的程序提供给 Rust 调用。然后编写 sorting.h 和 sorting.cpp:
然后给 Cargo.toml 的 [build-dependecies] 加上 cc crate 依赖:
接着,我们通过 cc 调用对应平台的c/c++编译器,因为我们这个项目是 WSL,所以和调用我们刚安装的 gcc:
接着,我们在 Rust 主程序中,通过 extern 块引入sorting.cpp中的interop_sort函数,并调用它:我们看到,该函数提示我们 C 中并没有等价于 Rust slice 的类型,原因在于如果我们传递 slice,那么在 C/C++ 中就很容易访问超过数组长度的内存,造成内存不安全问题。但是,我们在 Rust 调用的时候,通过同时传入数组 arr 的长度 arr.len(), 来保证函数不会访问未经授权的内存。不过在实践中,应该划分模块,只允许确认过 内存安全的 safe Rust 功能跨越模块调用。在 C/C++ 中调用 Rust
然后配置 Rust 生成两种库——静态库(staticlib)和c动态库(cdylib):
编写 makefile,先调度cargo 编译出我们需要的 Rust 库(动态或链接),然后再运行:
小结
本文通过给出两个简单的示例来展示 Rust 通过 FFI 功能与 C/C++ 生态进行交互的能力, 并且指出几个在实践过程中容易浪费时间的坑:
- WSL的环境变量不生效 -> 使用
WSLENV 变量从 Windows 引入使用。
make share 的时候提示 libcallrust.so 找不到 -> 需要在运行时指定 LD_LIBRARY_PATH 变量,引入我们编译的 libcallrust.so 路径。
make static的时候遇到了pthread_* dy*系列函数未定义问题 -> 通过动态链接系统库来支持运行。
原文链接:http://huangjj27.gitlab.io/about/
原文作者:Rust语言中文社区;如有侵权,请联系管理员删除。