91.将指针还原成指定类型
因为指针不知道里面具体有什么,所以一般约定打上unsafe
申明开发者自己对该部分可用性负责,且在调试的时候也能起强调作用
// tests6.rs
//
// In this example we take a shallow dive into the Rust standard library's
// unsafe functions. Fix all the question marks and todos to make the test
// pass.
//
// Execute `rustlings hint tests6` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
struct Foo {
a: u128,
b: Option<String>,
}
/// # Safety
///
/// The `ptr` must contain an owned box of `Foo`.
unsafe fn raw_pointer_to_box(ptr: *mut Foo) -> Box<Foo> {
// SAFETY: The `ptr` contains an owned box of `Foo` by contract. We
// simply reconstruct the box from that pointer.
let mut ret: Box<Foo> = unsafe { Box::from_raw(ptr) };
// todo!("The rest of the code goes here")
ret.b = Some("hello".to_owned());
ret
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Instant;
#[test]
fn test_success() {
let data = Box::new(Foo { a: 1, b: None });
let ptr_1 = &data.a as *const u128 as usize;
// SAFETY: We pass an owned box of `Foo`.
let ret = unsafe { raw_pointer_to_box(Box::into_raw(data)) };
let ptr_2 = &ret.a as *const u128 as usize;
assert!(ptr_1 == ptr_2);
assert!(ret.b == Some("hello".to_owned()));
}
}
92.配置本地环境
首先我们得知道配置文件放在build.rs里面!!!
首先参考文档之后写上指令
"rustc-env=TEST_FOO={}",
然后注释掉下面的 your_command变量即可通过test7
93. 函数签名设置编译参数
这个标签指定了编译的配置参数key-value
设置编译的key-value即可,详情参照文档
let your_command = "rustc-cfg=feature = \"pass\"";
94.设置#[link_name = "myName"]和#[no_mangle]获取原汁原味特定的函数名
有时候经过名称修饰或者编译,函数名会发生变化,在同语言下没有影响,但是在不同语言交互的时候可能会找不到指定的函数名,所以将函数名称固定可以避免此种情况发生
// tests9.rs
//
// Rust is highly capable of sharing FFI interfaces with C/C++ and other statically compiled
// languages, and it can even link within the code itself! It makes it through the extern
// block, just like the code below.
//
// The short string after the `extern` keyword indicates which ABI the externally imported
// function would follow. In this exercise, "Rust" is used, while other variants exists like
// "C" for standard C ABI, "stdcall" for the Windows ABI.
//
// The externally imported functions are declared in the extern blocks, with a semicolon to
// mark the end of signature instead of curly braces. Some attributes can be applied to those
// function declarations to modify the linking behavior, such as #[link_name = ".."] to
// modify the actual symbol names.
//
// If you want to export your symbol to the linking environment, the `extern` keyword can
// also be marked before a function definition with the same ABI string note. The default ABI
// for Rust functions is literally "Rust", so if you want to link against pure Rust functions,
// the whole extern term can be omitted.
//
// Rust mangles symbols by default, just like C++ does. To suppress this behavior and make
// those functions addressable by name, the attribute #[no_mangle] can be applied.
//
// In this exercise, your task is to make the testcase able to call the `my_demo_function` in
// module Foo. the `my_demo_function_alias` is an alias for `my_demo_function`, so the two
// line of code in the testcase should call the same function.
//
// You should NOT modify any existing code except for adding two lines of attributes.
// I AM NOT DONE
extern "Rust" {
fn my_demo_function(a: u32) -> u32;
#[link_name = "my_demo_function"]
fn my_demo_function_alias(a: u32) -> u32;
}
mod Foo {
#[no_mangle]
// No `extern` equals `extern "Rust"`.
fn my_demo_function(a: u32) -> u32 {
a
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_success() {
// The externally imported functions are UNSAFE by default
// because of untrusted source of other languages. You may
// wrap them in safe Rust APIs to ease the burden of callers.
//
// SAFETY: We know those functions are aliases of a safe
// Rust function.
unsafe {
my_demo_function(123);
my_demo_function_alias(456);
}
}
}
ok完结