使用extern函數設用外部代碼
有時我們的Rust代碼可能需要與其它語言編寫的代碼交互。為此Rust有一個關鍵字,extern,有助於創建和使用 外部函數接口(Foreign Function Interface, FFI)。外部函數接口是一個編程語言用以定義函數的方式,其允許不同(外部)編程語言調用這些函數。
示例1展示了如何集成C標准庫中的abs函數。extern塊中聲明的函數在Rust代碼中總是不安全的。因為其它語言不會強制執行Rust的規則且Rust無去檢查它們,所以確保其安全是程序員的責任:
extern "C" { fn abs(input: i32) -> i32; } //調用 unsafe { println!("Absolute value of -3 according to C: {}", abs(-3)); }
在extern "C"塊中,列出了我們希望能夠調用的另一個語言中的外部函數的簽名和名稱。"C"部分定義了外部函數所使用的 應用二進制接口 (application binary interface,ABI) -- ABI定義了如何在匯編語言層面調用此函數。"C" ABI是最常見的,並遵循C編程語言的ABI。
從其它語言調用Rust函數
也可以使用 extern 來創建一個允許其他語言調用Rust函數的接口。不同於extern塊,就在fn關鍵字之前增加extern關鍵字並指定所用的ABI。還需增加 #[no_mangle] 注解來告訴Rust編譯器不要mangle此函數的名稱。Mangling發生於當編譯器將我們指定的函數名修改為不同的名稱時,這會增加用於其它編譯過程的額外信息,不過會使其名稱更難以閱讀。每一個編程語言的編譯器都會以稍微不同的方式mangle函數名,所以為了使Rust函數能在其他語言中指定,必須禁用Rust編譯器的 name mangling。
在如下的例子中,一旦其編譯為動態庫從C語言中鏈接,call_from_c 函數就能夠在C代碼中訪問:
#[no_mangle] pub extern "C" fn call_from_c() { println!("Just called a Rust function from C"); }
extern 的使用無需 unsafe。