From a14def4fe3878187440d03b1ecd56763d19f7508 Mon Sep 17 00:00:00 2001 From: lijinpeng Date: Sun, 13 Feb 2022 20:14:42 +0800 Subject: [PATCH] Fix typo in unsafe/superpowers.md --- book/contents/advance/unsafe/superpowers.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/book/contents/advance/unsafe/superpowers.md b/book/contents/advance/unsafe/superpowers.md index 5b328e40..b01c2d38 100644 --- a/book/contents/advance/unsafe/superpowers.md +++ b/book/contents/advance/unsafe/superpowers.md @@ -91,7 +91,7 @@ unsafe { } ``` -使用 `*` 可以对原生指针进行解引用,由于该指针的内存安全性并没有任何保证,因此我们需要使用 `unsafe` 来包裹解引用的逻辑(切记,`unsafe` 语句块的范围一定要尽力的小,具体原因在上一章节有讲)。 +使用 `*` 可以对原生指针进行解引用,由于该指针的内存安全性并没有任何保证,因此我们需要使用 `unsafe` 来包裹解引用的逻辑(切记,`unsafe` 语句块的范围一定要尽可能的小,具体原因在上一章节有讲)。 以上代码另一个值得注意的点就是:除了使用 `as` 来显式的转换,我们还使用了隐式的转换方式 `let c: *const i32 = &a;`。在实际使用中,我们建议使用 `as` 来转换,因为这种显式的方式更有助于提醒用户:你在使用的指针是原生指针,需要小心。 @@ -145,7 +145,7 @@ unsafe { ## 用安全抽象包裹 unsafe 代码 一个函数包含了 `unsafe` 代码不代表我们需要将整个函数都定义为 `unsafe fn`。事实上,在标准库中有大量的安全函数,它们内部都包含了 `unsafe` 代码块,下面我们一起来看看一个很好用的标准库函数:`split_at_mut`。 -大家可以想象一下这个场景:需要将一个数组分成两个切片,且每一个切片都要求可变的。类似需求在安全 Rust 中是很难实现的,因为要对同一个数组做两个可变借用: +大家可以想象一下这个场景:需要将一个数组分成两个切片,且每一个切片都要求是可变的。类似需求在安全 Rust 中是很难实现的,因为要对同一个数组做两个可变借用: ```rust fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { let len = slice.len(); @@ -245,13 +245,13 @@ zsh: segmentation fault 前者相当不错,但是在很多时候,并没有那么多时间去重写,因此 `FFI` 就成了最佳选择。回到 Rust 语言上,由于这门语言依然很年轻,一些生态是缺失的,我们在写一些不是那么大众的项目时,可能会同时遇到没有相应的 Rust 库可用的尴尬境况,此时通过 `FFI` 去调用 C 语言的库就成了相当棒的选择。 -还有在将 C/C++ 的代码重构为时,先将相关代码引入到 Rust 项目中,然后逐步重构,也是不错的(为什么用不错来形容?因为重构一个有一定规模的 C/C++ 项目远没有想象中美好,因此最好的选择还是对于新项目使用 Rust 实现,老项目。。就让它先运行着吧)。 +还有在将 C/C++ 的代码重构为 Rust 时,先将相关代码引入到 Rust 项目中,然后逐步重构,也是不错的(为什么用不错来形容?因为重构一个有一定规模的 C/C++ 项目远没有想象中美好,因此最好的选择还是对于新项目使用 Rust 实现,老项目。。就让它先运行着吧)。 当然,除了 `FFI` 还有一个办法可以解决跨语言调用的问题,那就是将其作为一个独立的服务,然后使用网络调用的方式去访问,HTTP,gRPC都可以。 言归正传,之前我们提到 `unsafe` 的另一个重要目的就是对 `FFI` 提供支持,它的全称是 `Foreign Function Interface`,顾名思义,通过 `FFI` , 我们的 Rust 代码可以跟其它语言的外部代码进行交互。 -下面的例子演示了如何调用 C 标准库中的 `abc` 函数: +下面的例子演示了如何调用 C 标准库中的 `abs` 函数: ```rust extern "C" { fn abs(input: i32) -> i32; @@ -267,7 +267,7 @@ fn main() { C 语言的代码定义在了 `extern` 代码块中, 而 `extern` 必须使用 `unsafe` 才能进行进行调用,原因在于其它语言的代码并不会强制执行 Rust 的规则,因此 Rust 无法对这些代码进行检查,最终还是要靠开发者自己来保证代码的正确性和程序的安全性。 #### ABI -在 `exetrn "C"` 代码块中,我们列出了想要调用的外部函数的签名。其中 `"C"` 定义了外部函数所使用的**应用二进制接口**`ABI` (application binary interface):`ABI` 定义了如何在汇编层面来调用该函数。在所有 `ABI` 中,C 语言的是最常见的。 +在 `exetrn "C"` 代码块中,我们列出了想要调用的外部函数的签名。其中 `"C"` 定义了外部函数所使用的**应用二进制接口**`ABI` (Application Binary Interface):`ABI` 定义了如何在汇编层面来调用该函数。在所有 `ABI` 中,C 语言的是最常见的。 #### 在其它语言中调用 Rust 函数 在 Rust 中调用其它语言的函数是让 Rust 利用其他语言的生态,那反过来可以吗?其他语言可以利用 Rust 的生态不?答案是肯定的。 @@ -282,7 +282,7 @@ pub extern "C" fn call_from_c() { 上面的代码可以让 `call_from_c` 函数被 `C` 语言的代码调用,当然,前提是将其编译成一个共享库,然后链接到 C 语言中。 -这里还有一个比较奇怪的注解 `#[no_mangle]`,它用于告诉 Rust 编译器:不要乱改函数的名称。Mangling的定义是:当Rust 因为编译需要去修改函数的名称,例如为了让名称包含更多的信息,这样其它的编译部分就能从该名称获取相应的信息,这种修改会导致函数名变得相当不可读。 +这里还有一个比较奇怪的注解 `#[no_mangle]`,它用于告诉 Rust 编译器:不要乱改函数的名称。 `Mangling` 的定义是:当 Rust 因为编译需要去修改函数的名称,例如为了让名称包含更多的信息,这样其它的编译部分就能从该名称获取相应的信息,这种修改会导致函数名变得相当不可读。 因此,为了让 Rust 函数能顺利被其它语言调用,我们必须要禁止掉该功能。