使用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。