Fn、FnMut 或 FnOnce 中的一个。闭包语法 || {} 实际上是 Fn 系列 trait 的语法糖,Rust 会为“环境”创建一个结构体,impl其中合适的一个 trait,并使用它。call()方法的函数。这样我们可以获取其中函数部分的指针,从而实现将闭包传递给 C 端代码。sum_square_cb 函数,接收两个整型参数 a, b,一个函数指针,一个void *;get_callback;sum_square_cb;hook 和get_callback,代码如下:ffi/example_10/src/main.rsunsafe extern fn hook<F>(result: c_int, user_data: *mut c_void)whereF: FnMut(c_int),{let closure = &mut *(user_data as *mut F);closure(result);}pub fn get_callback<F>(_closure: &F) -> SumSquareCBwhereF: FnMut(c_int),{hook::<F>}
hook函数时,我们限定闭包实现为FnMut并以c_int作为参数。在函数体中的这一句 let closure = &mut *(user_data as *mut F); ,先通过把 *mut c_void 指针转换成 *mut F 指针,然后用 * 取得它的数据块,并使用 &mut 取得可变引用 ,最后调用闭包。get_callback函数中仅有的语句,hook::<F>,我们使用了一个叫做 turbofish ::<> 的语法,用来显式指定返回F类型的hook函数。fn main() {let mut record = SumRecord::default();unsafe {let mut closure = |result: c_int| {record.total += result;record.calls += 1;};let callback = get_callback(&closure);sum_square_cb(1, 2, callback, &mut closure as *mut _ as *mut c_void);sum_square_cb(3, 4, callback, &mut closure as *mut _ as *mut c_void);}println!("The sum is {:?}", record);}
let mut closure 语句意味着 closure 包含一个匿名函数的 定义,而不是调用后的 返回值,该函数接受一个c_int类型的参数。我们使用闭包的原因是需要事先定义一段代码,并在之后的某个时候才实际调用它。这里我们将期望调用的代码储存在了 closure 中。get_callback,其中有一点非常重要,它返回的函数指针只能在传入的同一闭包上使用。因为我们定义hook函数时在未进行任何类型检查的情况下,将user_data直接转换为该闭包类型的指针。sum_square_cb时,我们通过获取闭包变量 closure的可变引用,并进行两次指针转换,将其强制转换为 void * 指针来获取其数据。其中我们使用了_占位符由 Rust 编译器来推断该位置的闭包类型。原文作者:Rust语言中文社区;如有侵权,请联系管理员删除。