Update chapter_3_22_1.md

This commit is contained in:
令狐一冲
2023-05-18 11:21:59 +08:00
committed by GitHub
parent c38d6ed67b
commit 1467432e3f

View File

@@ -37,4 +37,108 @@ fn main() {
![注释](../../assets/51.png)
- 构建脚本的生命周期
在项目构建之前Cargo会将build.rs编译成可执行文件然后执行。在执行过程中脚本可以使用println的方式跟Cargo进行通信通信内容的格式为cargo:真正的内容。示例如下:
```Rust
// build.rs
fn main() {
println!("cargo:rustc-link-search=/usr/local/lib/");
println!("cargo:rustc-link-lib=dylib=pcre2-8");
println!("cargo:rerun-if-changed=src/lib.rs");
}
```
- 构建脚本的输入
可以通过环境变量、文件等方式给构建脚本提供一些输入。
- 构建脚本的输出
如果构建脚本生成文件可以指定该文件的输入目录可以通过设置OUT_DIR环境变量来指定。构建脚本的输出通常是用来告诉Cargo一些信息以下几个为常用的Cargo能识别的通信指令
- cargo:rerun-if-changed=PATH — 当指定路径的文件发生变化时Cargo会重新运行脚本
- cargo:rerun-if-env-changed=VAR — 当指定的环境变量发生变化时Cargo会重新运行脚本
- cargo:rustc-link-lib=[KIND=]NAME — 告诉Cargo通过-l去链接一个指定的库常用于FFI
- cargo:rustc-link-search=[KIND=]PATH — 告诉Cargo通过-L将一个目录添加到依赖库搜索路径中
- cargo:rustc-env=VAR=VALUE — 设置一个环境变量。
- 构建脚本的依赖
构建脚本也可以引入其它基于Cargo的依赖包依赖方式为在Cargo.toml中添加依赖包示例如下
```TOML
# Cargo.toml
...
[build-dependencies]
cc = "1.0.46" # 可以在build.rs中使用cc相关的功能
```
可以看到有一个foo.txt文件该文件就是在build.rs中生成的。
## 2. 在Rust中调用C代码
在Rust中调用c的代码需要使用extern关键字来定义外部函数接口即用extern块把c提供的函数接口进行封装。
下面的示例展示如何在Rust中使用c代码整个项目的目录结构如下
![注释](../../assets/52.png)
c目录中的pass.c为c代码源码如下
```Rust
// c/pass.c
#include <stdio.h>
void set_err(char *message) { // 提供一个打印错误信息的函数
printf("err: %s\n", message);
}
src目录中为Rust代码
// ==================
// 封装c函数
extern "C" { // 在Rust中调用c的代码需要使用extern关键字定义外部函数接口
// 实际上就是: 用extern块将c提供的函数接口封装下
fn set_err(message: *const libc::c_char);
}
// ==================
fn main() {
let err = "some error".to_string();
let c_err = std::ffi::CString::new(err).expect("error");
unsafe { // 需要unsafe块
set_err(c_err.as_ptr()); // 调用封装的c函数
}
}
```
build.rs中的内容如下
```Rust
// build.rs
fn main() {
// 以下代码告诉 Cargo `c/pass.c`发生改变,就重新运行当前的构建脚本
println!("cargo:rerun-if-changed=src/hello.c");
// 使用 `cc` 来构建一个 C 文件,然后进行静态链接
cc::Build::new()
.file("c/pass.c")
.compile("pass");
}
```
Cargo.toml中的内容如下
```TOML
[package]
name = "use-c"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
cc = "1.0.46" # build.rs中依赖cc所以此处需要添加
[dependencies]
libc = "0.2.139" # src/main.rs中使用了libc这个库
```