本文简要介绍rust语言中 Primitive Type fn
的用法。
函数指针,例如 fn(usize) -> bool
。
函数指针是指向的指针代码,不是数据。它们可以像函数一样被调用。与引用一样,函数指针除其他外被假定不为空,因此如果您想通过 FFI 传递函数指针并能够容纳空指针,请使您的类型Option<fn()>
以及您所需的签名。
安全性
普通函数指针是通过强制转换普通函数或不捕获环境的闭包来获得的:
fn add_one(x: usize) -> usize {
x + 1
}
let ptr: fn(usize) -> usize = add_one;
assert_eq!(ptr(5), 6);
let clos: fn(usize) -> usize = |x| x + 5;
assert_eq!(clos(5), 10);
除了根据签名而变化之外,函数指针还有两种类型:安全和不安全。普通fn()
函数指针只能指向安全函数,而unsafe fn()
函数指针可以指向安全或不安全函数。
fn add_one(x: usize) -> usize {
x + 1
}
unsafe fn add_one_unsafely(x: usize) -> usize {
x + 1
}
let safe_ptr: fn(usize) -> usize = add_one;
//ERROR: mismatched types: expected normal fn, found unsafe fn
//let bad_ptr: fn(usize) -> usize = add_one_unsafely;
let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
ABI
最重要的是,函数指针可能会根据它们使用的 ABI 而有所不同。这是通过在类型前添加 extern
关键字,然后是相关 ABI 来实现的。默认 ABI 为 “Rust”,即 fn()
与 extern "Rust" fn()
的类型完全相同。指向具有 C ABI 的函数的指针将具有类型 extern "C" fn()
。
extern "ABI" { ... }
块使用 ABI “ABI” 声明函数。此处的默认值为“C”,即在extern {...}
块中声明的函数具有“C” ABI。
有关详细信息和支持的 ABI 列表,请参阅nomicon 关于外国调用约定的部分.
可变函数
带有 “C” 或 “cdecl” ABI 的外部函数声明也可以可变参数,允许使用可变数量的参数来调用它们。正常的 Rust 函数,即使是那些带有extern "ABI"
, 不能是可变的。有关详细信息,请参阅nomicon 关于可变参数函数的部分.
创建函数指针
什么时候bar
是函数名,然后是表达式bar
是不是函数指针。相反,它表示唯一标识该函数的不可命名类型的值bar
。该值的大小为零,因为类型已经标识了该函数。这样做的优点是 “calling” 值(它实现了Fn*
特征)不需要动态调度。
这种大小为零的类型强制转换为常规函数指针。例如:
use std::mem;
fn bar(x: i32) {}
let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
assert_eq!(mem::size_of_val(¬_bar_ptr), 0);
let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
最后一行显示&bar
也不是函数指针。相反,它是对function-specific ZST 的引用。当bar
是一个函数时,&bar
本质上永远不是你想要的。
特性
函数指针实现以下特征:
- std::clone::Clone
- std::cmp::PartialEq
- std::cmp::Eq
- std::cmp::PartialOrd
- std::cmp::Ord
- std::hash::Hash
- std::fmt::Pointer
Debug
由于 Rust 类型系统的临时限制,这些特征仅在具有 12 个或更少参数的函数上实现,带有 "Rust"
和 "C"
ABI。将来,这种情况可能会改变。
另外,函数指针任何签名、ABI 或安全性std::marker::Copy, 和所有安全的函数指针实现std::ops::Fn,std::ops::FnMut, 和std::ops::FnOnce。这是可行的,因为这些特征是编译器特别已知的。
相关用法
- Rust f32.exp用法及代码示例
- Rust f32.hypot用法及代码示例
- Rust f32.minimum用法及代码示例
- Rust f64.signum用法及代码示例
- Rust f64.sqrt用法及代码示例
- Rust f32.sqrt用法及代码示例
- Rust f32.abs_sub用法及代码示例
- Rust f64.is_finite用法及代码示例
- Rust f32.cos用法及代码示例
- Rust f32.is_sign_positive用法及代码示例
- Rust f32.log10用法及代码示例
- Rust f64.round用法及代码示例
- Rust format_args用法及代码示例
- Rust f32.total_cmp用法及代码示例
- Rust f64.div_euclid用法及代码示例
- Rust f64.hypot用法及代码示例
- Rust f32.from_ne_bytes用法及代码示例
- Rust f32.recip用法及代码示例
- Rust f64.floor用法及代码示例
- Rust f64.log用法及代码示例
- Rust from_u32_unchecked用法及代码示例
- Rust f64.asinh用法及代码示例
- Rust f64.classify用法及代码示例
- Rust f32.sinh用法及代码示例
- Rust f32.ln_1p用法及代码示例
注:本文由纯净天空筛选整理自rust-lang.org大神的英文原创作品 Primitive Type fn。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。