Skip to content

进阶

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!()

用于在不返回的函数中充当返回类型

动态大小

高级类型 - Rust 程序设计语言 简体中文版

高级函数和闭包

函数指针

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 {
}

自定义derive宏

宏 - Rust 程序设计语言 简体中文版