# 不使用标准库
> [no-stdlib.md](https://github.com/rust-lang/rust/blob/master/src/doc/book/no-stdlib.md)
commit 0394418752cd39c5da68e7e05d5a37bf5a30f0db
Rust 的标准库提供了很多有用的功能,不过它假设它的 host 系统的多种功能的支持:线程,网络,堆分配和其他功能。有些系统并没有这些功能,不过,Rust也能在这些系统上工作。为此,我们可以通过一个属性来告诉 Rust 我们不想使用标准库:`#![no_std]`。
> 注意:这个功能技术上是稳定的,不过有些附加条件。其一,你可以构建一个稳定的`#![no_std]`库,但二进制文件不行。关于没有标准库的库文件的细节,查看[关于`#![no_std]`的章节](https://github.com/rust-lang/rust/blob/master/src/doc/book/using-rust-without-the-standard-library.html)。
被标记为`#[start]`的函数传递的参数格式与 C 一致:
~~~
# #![feature(libc)]
#![feature(lang_items)]
#![feature(start)]
#![no_std]
// Pull in the system libc library for what crt0.o likely requires
extern crate libc;
// Entry point for this program
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
// These functions and traits are used by the compiler, but not
// for a bare-bones hello world. These are normally
// provided by libstd.
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
# #[no_mangle] pub extern fn rust_eh_register_frames () {}
# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
# // fn main() {} tricked you, rustdoc!
~~~
要覆盖编译器插入的`main`shim,你必须使用`#![no_main]`禁用它并通过正确的 ABI 和正确的名字来创建合适的函数,这也需要需要覆盖编译器的命名改编:
~~~
# #![feature(libc)]
#![feature(lang_items)]
#![feature(start)]
#![no_std]
#![no_main]
extern crate libc;
#[no_mangle] // ensure that this symbol is called `main` in the output
pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
0
}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
# #[no_mangle] pub extern fn rust_eh_register_frames () {}
# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
# // fn main() {} tricked you, rustdoc!
~~~
目前编译器对能够被可执行文件调用的符号做了一些假设。正常情况下,这些函数是由标准库提供的,不过没有它你就必须定义你自己的了。
这三个函数中的第一个`stack_exhausted`,当检测到栈溢出时被调用。这个函数对于如何被调用和应该干什么有一些限制,不顾如果栈限制寄存器没有被维护则一个线程可以有”无限的栈“,这种情况下这个函数不应该被触发。
第二个函数,`eh_personality`,被编译器的错误机制使用。它通常映射到 GCC 的特性函数上(查看[libstd实现](http://doc.rust-lang.org/std/rt/unwind/)来获取更多信息),不过对于不会触发恐慌的包装箱可以确定这个函数不会被调用。最后一个函数,`panic_fmt`,也被编译器的错误机制使用。
> 如下内容已被删除,暂时保留
### 使用 libcore
> **注意**:核心库的结构是不稳定的,建议在任何可能的情况下使用标准库。
通过上面的计数,我们构造了一个少见的运行Rust代码的可执行程序。标准库提供了很多功能,然而,这是Rust的生产力所需要的。如果标准库是不足的话,那么可以使用被设计为标准库替代的[libcore](http://doc.rust-lang.org/core/)。
核心库只有很少的依赖并且比标准库可移植性更强。另外,核心库包含编写符合习惯和高效Rust代码的大部分功能。
例如,下面是一个计算由C提供的两个向量的数量积的函数,使用常见的Rust实现。
~~~
# #![feature(libc)]
#![feature(lang_items)]
#![feature(start)]
#![feature(raw)]
#![no_std]
extern crate libc;
use core::mem;
#[no_mangle]
pub extern fn dot_product(a: *const u32, a_len: u32,
b: *const u32, b_len: u32) -> u32 {
use core::raw::Slice;
// Convert the provided arrays into Rust slices.
// The core::raw module guarantees that the Slice
// structure has the same memory layout as a &[T]
// slice.
//
// This is an unsafe operation because the compiler
// cannot tell the pointers are valid.
let (a_slice, b_slice): (&[u32], &[u32]) = unsafe {
mem::transmute((
Slice { data: a, len: a_len as usize },
Slice { data: b, len: b_len as usize },
))
};
// Iterate over the slices, collecting the result
let mut ret = 0;
for (i, j) in a_slice.iter().zip(b_slice.iter()) {
ret += (*i) * (*j);
}
return ret;
}
#[lang = "panic_fmt"]
extern fn panic_fmt(args: &core::fmt::Arguments,
file: &str,
line: u32) -> ! {
loop {}
}
#[lang = "eh_personality"] extern fn eh_personality() {}
# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
# #[no_mangle] pub extern fn rust_eh_register_frames () {}
# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
# fn main() {}
~~~
注意这里有一个额外的`lang`项与之前的例子不同,`panic_fmt`。它必须由libcore的调用者定义因为核心库声明了恐慌,但没有定义它。`panic_fmt`项是这个包装箱的恐慌定义,并且它必须确保不会返回。
正如你在例子中所看到的,核心库尝试在所有情况下提供Rust的功能,不管平台的要求如何。另外一些库,例如`liballoc`,为libcore增加了进行其它平台相关假设的功能,不过这依旧比标准库更有可移植性。
- 前言
- 贡献者
- 1.介绍
- 2.准备
- 3.学习 Rust
- 3.1.猜猜看
- 3.2.哲学家就餐问题
- 3.3.其它语言中的 Rust
- 4.语法和语义
- 4.1.变量绑定
- 4.2.函数
- 4.3.原生类型
- 4.4.注释
- 4.5.If语句
- 4.6.循环
- 4.7.所有权
- 4.8.引用和借用
- 4.9.生命周期
- 4.10.可变性
- 4.11.结构体
- 4.12.枚举
- 4.13.匹配
- 4.14.模式
- 4.15.方法语法
- 4.16.Vectors
- 4.17.字符串
- 4.18.泛型
- 4.19.Traits
- 4.20.Drop
- 4.21.if let
- 4.22.trait 对象
- 4.23.闭包
- 4.24.通用函数调用语法
- 4.25.crate 和模块
- 4.26.const和static
- 4.27.属性
- 4.28.type别名
- 4.29.类型转换
- 4.30.关联类型
- 4.31.不定长类型
- 4.32.运算符和重载
- 4.33.Deref强制多态
- 4.34.宏
- 4.35.裸指针
- 4.36.不安全代码
- 5.高效 Rust
- 5.1.栈和堆
- 5.2.测试
- 5.3.条件编译
- 5.4.文档
- 5.5.迭代器
- 5.6.并发
- 5.7.错误处理
- 5.8.选择你的保证
- 5.9.外部函数接口
- 5.10.Borrow 和 AsRef
- 5.11.发布途径
- 5.12.不使用标准库
- 6.Rust 开发版
- 6.1.编译器插件
- 6.2.内联汇编
- 6.4.固有功能
- 6.5.语言项
- 6.6.链接进阶
- 6.7.基准测试
- 6.8.装箱语法和模式
- 6.9.切片模式
- 6.10.关联常量
- 6.11.自定义内存分配器
- 7.词汇表
- 8.语法索引
- 9.参考文献
- 附录:名词中英文对照