进阶¶
Unsafe Rust¶
解引用原始指针¶
错误
fn main() {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
println!("r1: {}",*r1); // dereference of raw pointer is unsafe and requires unsafe function or block
println!("r2: {}",*r2);
let address = 0x012345usize;
let r = address as *const i32;
}
正确
fn main() {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
println!("r1: {}",*r1);
println!("r2: {}",*r2);
}
let address = 0x012345usize;
let r = address as *const i32;
}
Unsafe关键字¶
unsafe fn dangerous() {}
fn main() {
dangerous(); // 报错
unsafe {
dangerous(); // 不报错
}
}
使用 extern 函数调用外部代码¶
任何extern块中的函数声明都是不安全的,因为其他编程语言是不安全的
应用ABI,定义函数在汇编层面的调用方式
从Rust函数调用其他语言¶
在 Rust 中,extern 可以用来声明外部函数、变量和类型,这些函数、变量和类型都是在其他语言中定义的。当 Rust 程序需要使用这些外部函数、变量和类型时,可以使用 extern 关键字将其导入。
例如,下面是导入一个外部 C 语言库的示例:
// 使用 extern 导入外部 C 语言库
extern "C" {
fn printf(format: *const u8, ...) -> i32; // 函数声明
}
fn main() {
// 调用 printf 函数
let msg = b"Hello, world!\0";
unsafe {
printf(b"%s\0".as_ptr(), msg.as_ptr());
}
}
在上面的示例中,我们使用 extern 关键字将 printf 函数导入到 Rust 程序中,并在 main 函数中调用了它。注意,在调用 printf 函数时,需要在 unsafe 块中执行,因为 printf 是一个外部函数,它的实现可能不符合 Rust 的安全要求。
除了使用 extern 导入 C 语言库之外,还可以使用 extern Rust 语言库或者其他语言库。在导入 Rust 语言库时,需要指定库的名称和版本号;在导入其他语言库时,则需要指定库的路径和名称。
其他语言调用rust
#[no_mangle]
pub extern "C" fn call_from_c() {
println!("Just called a Rust function from C!")
}
fn main() {}
访问或修改一个静态变量¶
static mut COUNTER: u32 = 0;
fn add_to_count(inc: u32) {
unsafe {
COUNTER += inc;
}
}
fn main() {
add_to_count(3);
unsafe {
println!("COUNTER: {}", COUNTER);
}
}
Unsafe trait¶
unsafe trait MyTrait {
fn my_func(&self) -> i32;
}
struct MyStruct {
value: i32,
}
unsafe impl MyTrait for MyStruct {
fn my_func(&self) -> i32 {
self.value * 2
}
}
fn main() {
let my_struct = MyStruct { value: 5 };
let my_trait: &dyn MyTrait = &my_struct;
unsafe {
println!("{}", my_trait.my_func());
}
}
高级Trait¶
关联类型¶
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
fn main() {
println!("Hello, world!");
}
可以为类型实现多个不同的trait
高级类型¶
类型别名¶
type i3 = i32;
fn main() {
let a:i3 = 0;
}
never类型¶
!
print!() // 返回值为「empty type」
panic!()
用于在不返回的函数中充当返回类型
动态大小¶
高级函数和闭包¶
函数指针¶
fn add_one(x: i32) -> i32 {
x + 1
}
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
f(arg) + f(arg)
}
fn main() {
let answer = do_twice(add_one, 5);
println!("The answer is: {}", answer);
}
返回闭包¶
错误
fn returns_closure() -> dyn Fn(i32) -> i32 { // Rust 并不知道需要多少空间来储存闭包
|x| x + 1
}
fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
Box::new(|x| x + 1)
}
宏¶
声明宏¶
#![allow(unused)]
fn main() {
let v: Vec<u32> = vec![1, 2, 3];
}
vec!宏的定义
#[macro_export]
macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}
#[macro_export]
注解表明只要导入了定义这个宏的 crate,该宏就应该是可用的。如果没有该注解,这个宏不能被引入作用域。
macro_rules! my_macro {
() => {
println!("Check out my macro!");
};
}
fn main() {
my_macro!();
}
类函数宏¶
use proc_macro;
#[some_attribute]
pub fn some_name(input: TokenStream) -> TokenStream {
}