Rust闭包实例分析

蜗牛 互联网技术资讯 2022-04-27 32 0

这篇“Rust闭包实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Rust闭包实例分析”文章吧。

闭包
我们知道 Rust 的闭包不仅是一个函数指针,这意味着不能使用它作为回调函数的函数指针直接传递给 C 端。同时我们也知道 Rust 中的所有的闭包都实现了由标准库提供的 trait    Fn  、  FnMut   或    FnOnce   中的一个。闭包语法    || {}   实际上是    Fn   系列 trait 的语法糖,Rust 会为“环境”创建一个结构体,  impl  其中合适的一个 trait,并使用它。因此,从理论上讲,我们应该能够通过将闭包“拆分”为两部分,匿名类型的实例数据和某种类似  call()  方法的函数。这样我们可以获取其中函数部分的指针,从而实现将闭包传递给 C 端代码。具体的方法就是:首先创建一个泛型 hook 函数,该函数和回调函数的参数列表一样,在其中构建并调用闭包。然后创建一个 getter 函数,该函数接受闭包的引用作为参数,返回一个函数指针。我们沿用上篇设计的示例,稍作修改:
  1. C 端, sum_square_cb  函数,接收两个整型参数 a, b,一个函数指针,一个 void *
  2. Rust 端,定义一个 getter 函数  get_callback
  3. Rust 端,定义一个闭包,被调用时更新数据 user_data;
  4. Rust 端,调用 C 中定义的  sum_square_cb
好,代码部分 C 端保持不变,我们看 Rust 端的两个函数  hook   和  get_callback  ,代码如下:
  
// ffi/example_10/src/main.rs
unsafe extern fn hook<F>(result: c_int, user_data: *mut c_void)where    F: FnMut(c_int),{    let closure = &mut *(user_data as *mut F);    closure(result);}
pub fn get_callback<F>(_closure: &F) -> SumSquareCBwhere    F: 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  函数。接下来我们 Rust 端的主函数,代码如下:
  
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  直接转换为该闭包类型的指针。同时在调用 C 端函数  sum_square_cb  时,我们通过获取闭包变量    closure  的可变引用,并进行两次指针转换,将其强制转换为    void *   指针来获取其数据。其中我们使用了  _  占位符由 Rust 编译器来推断该位置的闭包类型。

以上就是关于“Rust闭包实例分析”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注蜗牛博客行业资讯频道。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

评论