# 不使用標準庫
> [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.參考文獻
- 附錄:名詞中英文對照